gpt4 book ai didi

javascript - 如何从模板外部调用 Angularjs 指令的方法?

转载 作者:行者123 更新时间:2023-11-30 05:36:54 25 4
gpt4 key购买 nike

我是 Angularjs 的新手,所以请多多包涵。

我想创建一个通用向导,让我可以完成一个过程。我首先创建了一个自定义指令来处理几乎所有“巫师”的东西……步骤、上一个和下一个等等。

虽然向导模板提供了用于在步骤之间移动的下一个和上一个按钮,但可能有一些操作会导致使用向导的 Controller / View 需要向向导指示它需要通过步。我还不知道该怎么做。我想也许 $emit 或 $broadcast 可能有用,但我想也许我在范围方面遗漏了一些东西。

看看这个例子:Plunker example它不漂亮,但它给了你想法。我希望能够做的是在用户选择订单时在向导中强制执行“下一步”。

这是我的指令的代码:

    angular.module("app")
.directive('rhWizard', [wizard])
.directive('rhStep', [step]);

function wizard() {
return {
restrict: "E",
transclude: true,
scope: {},
controller: function ($scope) {
var steps = $scope.steps = [];
$scope.selectedIndex = 0;
$scope.selectedStep = {};
$scope.$on('wizNext', function () {
$scope.next();
});
$scope.next = function () {
var result = $scope.selectedStep.completed();
if (!result)
return;

var _next = $scope.selectedIndex + 1;
if (_next < steps.length) {
$scope.select(steps[_next]);
}
};

$scope.prev = function () {
var _next = $scope.selectedIndex - 1;
if (_next > -1) {
$scope.select(steps[_next]);
}
}

$scope.select = function (step) {
for (var x = 0; x < steps.length; x++) {
if (steps[x] == step) {
$scope.selectedIndex = x;
$scope.selectedStep = step;
steps[x].selected = true;
}
else {
steps[x].selected = false;
}
}
};

this.addStep = function (step) {
steps.push(step);
step.id = steps.length;
if (steps.length === 1) {
$scope.select(step);
}
};
},
templateUrl: "/Scripts/app/common/rhwizard.html"
}
};

function step() {
return {
require: '^rhWizard',
restrict: 'E',
transclude: true,
scope: {
title: '@',
completed: '&isComplete',
nextText: '@',
prevText: '@'
},
link: function (scope, element, attrs, wizCtrl) {
wizCtrl.addStep(scope);
},
templateUrl: '/Scripts/app/common/rhsteps.html'
};
};

和模板代码(rhwizard.html):

<div class="fuelux">
<div class="wizard">
<ul class="steps">
<li ng-class="{active: step.selected, complete: step.id <= selectedIndex }" ng-repeat="step in steps" ng-click="select(step)">
<span class="badge" ng-class="{'badge-info': step.selected, 'badge-success': step.id <= selectedIndex}" >{{step.id}}</span>{{step.title}}<span class="chevron">
</span>
</li>
</ul>
<div class="actions">
<button class="btn btn-primary btn-mini" ng-click="prev()" ng-disabled="selectedStep.id == 1"><i class="fa fa-chevron-left"></i> {{selectedStep.prevText || "Prev"}}</button>
<button class="btn btn-primary btn-mini" ng-click="next()" ng-disabled="selectedStep.id >= steps.length" >{{selectedStep.nextText || "Next" }} <i class="fa fa-chevron-right"></i></button>
</div>
</div>
<div class="step-content" style="padding-top:20px;" ng-transclude></div>

(rhstep.html)

<div ng-class="{active: selected}" class="step-pane" ng-transclude>
</div>

以及正在使用的代码片段:

<div ng-app="app" ng-controller="orders as vm">
<rh-wizard>
<rh-step title="Select an order">
<div ng-repeat="order in vm.orders" ng-click="next()"></div>
</rh-step>
<rh-step title="Select a filter">
<p>This is the content</p>
</rh-step>
</rh-wizard>
</div>

最佳答案

通常处理此类事情的方式是使用服务进行协调。状态由服务管理,指令只响应状态的变化,只要它需要修改DOM,隐藏或显示元素等。你外面的 Controller 也可以注入(inject)这个服务并调用方法来改变状态,例如向前或向后移动步骤,重置向导等。

服务可能会广播状态更改事件,例如步骤更改,并且指令会监听这些事件以更新 View 。

或者,也许与服务一致,您只需要一个代表向导状态的众所周知的对象;步骤,哪个步骤是事件的,已经完成等。然后将该状态作为双向绑定(bind)范围项从 Controller 提供给指令。然后,您的指令可以对该范围项进行深度 $watch 以获取任何更改并适本地显示它们。现在,我提到“与服务一致”。我的意思是服务的 Action ,例如前进或后退,可以在这个向导状态对象上运行。这是更可取的,因为您可以制定可以进行单元测试的众所周知的操作,而不是将其留给开发人员以确保他们针对他们希望表达的操作适本地修改状态对象。

这两个建议之间的区别在于,首先,状态完全包含在服务中,它只是在需要消费者对某个操作使用react时通知消费者。后者有点松散,因为状态直接在 View 的 Controller 和指令的 Controller 之间协调,如果您选择仍然拥有服务,它只是为了确保操作以一致和可靠的方式完成。当然,这些不是您唯一的选择。哪个最好?这取决于您的需要以及您的向导的复杂程度。对于前者,您必须记住重置状态,如果您使用多个向导,请想出一种方法让它知道您的 View 正在使用哪个向导。对于多或复杂的向导系统来说,这似乎是值得的。如果您需要的向导微不足道并且只使用一次,那么后者可能会快速而肮脏但足够好。

I forked your plunk包括指令和任何其他组件都可以使用的向导服务。

.factory('wizard', function() {
// private state
var state = {
steps: [],
selectedIndex: 0,
};

// public methods for manipulating the state
return {
next: function() {
var i = state.selectedIndex + 1;
if (i < state.steps.length) this.select(state.steps[i]);
},
prev: function() {
var i = state.selectedIndex - 1;
if (i > -1) this.select(state.steps[i]);
},
select: function(step) {
for(var x = 0; x < state.steps.length; x++){
var current = state.steps[x];

if ((angular.isNumber(step) && step === x) || current == step) {
current.selected = true;
state.selectedIndex = x;
} else {
current.selected = false;
}
}
},
addStep: function(step) {
state.steps.push(step);

if (state.steps.length === 1) this.select(step);
},
// lets a consumer get or set the current state. this is how the wizard directive grabs the state which is binds to in the template
state: function(newState) {
if (arguments.length === 0) return state;
if (newState) {
state = newState;
if (!state.steps) state.steps = [];
if (isNaN(state.selectedIndex)) state.selectedIndex = 0;
}
}
};
})

关于javascript - 如何从模板外部调用 Angularjs 指令的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23141153/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com