Angular / Ionic:当我更新控制器中的变量时,如何刷新指令?

时间:2016-06-15 16:29:35

标签: javascript angularjs ionic-framework

我有'问题'控制器,它在HTML中包含一组输入类型的指令:

<my-text ng-attr-ref="{{ref}}" ng-if="type=='text'"></my-text> 
<my-integer ng-attr-ref="{{ref}}" ng-if="type=='integer'"></my-integer> 
<my-decimal ng-attr-ref="{{ref}}" ng-if="type=='decimal'"></my-decimal>

要在每个问题之间导航,我只需将'ref'更新为下一个问题'ref'然后更新问题的类型等,而angular会根据上面的指令显示相应的输入类型,并隐藏先前的输入。

我在上述每个指令中使用链接函数来设置问题文本并绑定到每个问题的答案。

angular.module('question.directives')
/**
* Text directive
*/
.directive('myText', function ($compile, PARAMETERS) {
    return {
        restrict: 'E',
        templateUrl: PARAMETERS.COMPONENTS_PATH + 'question/inputs/text/my-text.html',
        scope: true,
        link: function (scope, element, attrs) {
            // Get closest parent scope
            var parent = scope.$parent;
            // Question input details
            var inputDetails = parent.inputs[attrs.ref].data;
            scope.question = inputDetails.question;
            // Set the answer for this question (based on answers stored in parent scope)
            scope.answer = parent.answers[attrs.ref];
        }
    };
});

这很好,直到我从一个文本输入导航到另一个文本输入,并且指令没有更新,所以我连续两次看到相同的问题。 从一种类型导航到另一种类型可以正常工作。

这是为了减少动态变量的闪烁,因为我之前使用$ state.go()转到同一个控制器,重新加载视图,并附带更新的问题详细信息。 这样,我重用了相同的html,只更新了我需要的指令,而不是再次创建整个视图。

有没有其他人在视图中闪烁的离子变量有这个问题,或者有人可以建议我可以强制控制器更新指令吗? 我已经在视图中设置了cache-view="false"

Here's a simple plunker。正如您将注意到的,当我从问题3到问题4单击“下一步”时,我会看到问题3两次,因为我连续两次使用my-text指令。同样,点击问题5中的“上一个”,连续两次向我显示问题4。

谢谢!

编辑: 所以我最终做的是将一个对象params添加到控制器范围,并将currentIndex作为属性添加到它。当我在链接函数中通过scope.$watch('params.currentIndex', update);观察时,它正确地调用了更新函数,该函数刷新了我的指令中的参数。

我添加了this新的plunker以反映我所做的更改。

2 个答案:

答案 0 :(得分:1)

好的,所以你使用链接函数更新显示的值,但链接函数只在编译时调用一次。 因此,在第一页加载时,您的指令被编译并且链接被调用。 然后转到下一个具有不同类型的问题,这会导致ng-if触发。现在ng-if从dom中删除了第一个指令,并将第二个指令添加到dom中,现在调用了link方法。

当你保留第一个指令时,它不会调用链接函数,因为你重用了指令。

我建议只使用标准角度绑定而不是链接功能,因为它只会自动为您更新。

如果您需要更多帮助,我将添加示例代码。

修改

angular
    .module('question.directives')
    .directive('myText', MyTextDirective);

function MyTextDirective($compile, PARAMETERS) {
    return {
        restrict: 'E',
        scope: {
            ref: '&'
        },
        templateUrl: PARAMETERS.COMPONENTS_PATH + 'question/inputs/text/my-text.html',
        controller: MyTextController
    };
}

function MyTextController($scope) {
    $scope.$watch(() => this.ref, update);

    function update() {
        $scope.question = $scope.$parent.inputs[this.ref].question;
        $scope.answer   = $scope.$parent.answers[this.ref];
    }
}

这样做是为了使用属性'ref'和控制器注册一个指令。控制器为属性'ref'注册一个观察者,并在每次'ref'的值改变时调用update()。

update()与您在链接功能中的操作相同,只是格式不同。

现在这不是超级有效但它应该有效。根据您的角度版本和周围的代码,您可以实现一个组件来获取问题和答案而不是参考,这将消除对观察者的需求。

您还可以公开在显示下一个问题时调用的函数,然后删除观察者。

答案 1 :(得分:0)

再试一次尝试,

的index.html

<div id="question">
  <my-text  ng-if="currentQuestion.type=='text'"></my-text>
  <my-integer  ng-if="currentQuestion.type=='integer'"></my-integer>
</div>

的script.js

$scope.next = function() {
    if ($scope.currentIndex < ($scope.questions.length - 1)) {
      $scope.currentIndex++;
      $scope.currentQuestion = $scope.questions[$scope.currentIndex];
    }
    updateDiv();
  }

  var updateDiv = function(){
    var elem = angular.element( document.querySelector( '#question' ) );
    elem.html("");
    var html = "<div><my-text  ng-if=\"currentQuestion.type=='text'\"></my-text><my-integer  ng-if=\"currentQuestion.type=='integer'\"></my-integer></div>";
    var compiledHTML = $compile(html)($scope);
    elem.append( compiledHTML );
  }

  $scope.previous = function() {
    if ($scope.currentIndex > 0) {
      $scope.currentIndex--;
      $scope.currentQuestion = $scope.questions[$scope.currentIndex];
    }
    updateDiv();
  }

有一个错误,但可以修复。我试图找到它。