Javascript 如何从外部调用Angularjs指令上的方法';什么样的模板?

Javascript 如何从外部调用Angularjs指令上的方法';什么样的模板?,javascript,angularjs,angularjs-directive,Javascript,Angularjs,Angularjs Directive,我是新来安格拉斯的,所以请容忍我 我想创建一个通用向导,使我能够遍历一个流程。我首先创建了一个自定义指令,它可以处理几乎所有的“向导”内容。。。步骤、上一步和下一步等 虽然向导模板提供了用于在步骤之间移动的“下一步”和“上一步”按钮,但可能有一些操作会导致使用向导的控制器/视图需要向向导指示它需要在某个步骤中向前或向后移动。我还不知道怎么做。我想$emit或$broadcast可能会起作用,但我想我可能在范围方面遗漏了一些东西 看看这个例子:它不漂亮,但它给了你想法。我希望能够做到的是,当用户选

我是新来安格拉斯的,所以请容忍我

我想创建一个通用向导,使我能够遍历一个流程。我首先创建了一个自定义指令,它可以处理几乎所有的“向导”内容。。。步骤、上一步和下一步等

虽然向导模板提供了用于在步骤之间移动的“下一步”和“上一步”按钮,但可能有一些操作会导致使用向导的控制器/视图需要向向导指示它需要在某个步骤中向前或向后移动。我还不知道怎么做。我想$emit或$broadcast可能会起作用,但我想我可能在范围方面遗漏了一些东西

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

以下是我的指令代码:

    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'
    };
};
角度模块(“应用程序”) .directive('rhWizard',[wizard]) .指令('rhStep',[step]); 函数向导(){ 返回{ 限制:“E”, 是的, 作用域:{}, 控制器:功能($scope){ var steps=$scope.steps=[]; $scope.selectedIndex=0; $scope.selectedStep={}; $scope.$on('wizNext',函数(){ $scope.next(); }); $scope.next=函数(){ var result=$scope.selectedStep.completed(); 如果(!结果) 返回; var _next=$scope.selectedIndex+1; 如果(_next-1){ $scope.select(步骤[_next]); } } $scope.select=函数(步骤){ 对于(var x=0;x 以及模板代码(rhwizard.html):


  • {{step.id}{{step.title}}
{{selectedStep.prevText | |“Prev”} {{selectedStep.nextText | |“下一步”}

(rhstep.html)


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

<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、隐藏或显示元素等时响应状态更改。外部控制器也可以注入此服务并调用方法来更改状态,例如向前或向后移动步骤、重置向导等

服务可能会广播状态更改的事件,例如步骤更改,指令会监听这些事件以更新视图

或者,也许与服务配合使用,您只需要有一个表示向导状态的知名对象;步骤(哪个步骤处于活动状态、哪个步骤已完成等)然后将该状态作为双向绑定范围项从控制器提供给指令。然后,您的指令可以对该范围项执行深度
$watch
,以查看任何更改,并适当地显示它们。现在,我提到“配合服务”。我的意思是,服务的操作(如向前或向后)可以在这个向导状态对象上运行。这是更可取的,因为您可以做出可以进行单元测试的众所周知的操作,而不是让开发人员来确保他们为希望表达的操作适当地修改状态对象

这两个建议的区别在于:第一,状态完全被服务所包围,当它希望消费者对某个动作做出反应时,它只是通知消费者。后者有点松散,因为状态直接在视图的控制器和指令的控制器之间进行协调,如果您选择继续使用服务,它只是为了确保以一致和可靠的方式完成操作。当然,这些不是你唯一的选择。哪一个最好?这取决于您的需要和向导的复杂程度。对于前者,您必须记住重置状态,如果您使用多个向导,请想出一种方法让它知道您的视图正在使用哪个向导。对于一个多向导或复杂的向导系统来说,这似乎是值得的。如果您需要的向导是t
<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>
.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;
      }
    }
  };
})