【问题标题】:Angular/Ionic: how can I refresh a directive when I update variables in the controller?Angular/Ionic:更新控制器中的变量时如何刷新指令?
【发布时间】:2023-03-06 14:29:01
【问题描述】:

我有一个“问题”控制器,它在 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,并且只更新了我需要的指令,而不是再次创建整个视图。

是否有其他人遇到过 Ionic 变量在视图中闪烁的问题,或者任何人都可以建议一种方法我可以强制控制器更新指令吗? 我已经在视图中设置了cache-view="false"。

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

谢谢!

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

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

【问题讨论】:

  • 你试过this 吗?你也应该尝试使用范围变量,而不是ng-attr-ref。
  • @zion 感谢您的链接,但 ui-if 似乎已从 angular 中删除,并且 ng-if 我已经在使用。似乎从一个文本输入切换到另一个文本输入发生得如此之快,它没有机会刷新。我尝试将'currentQuestion.type'设置为null,然后添加一个setTimeout,延迟500毫秒,我将'currentQuestion.type'设置回'text'并且这有效。不过我不想在那里设置一个 setTimeout ......
  • 还有一个建议,将指令放在开头的 div 中.. 当单击上一个或下一个按钮时.. 1. 清空 div 2. 重新编译指令 3. 将它们附加到Div...这是一个hack,但这应该可以工作..
  • 感谢您的建议,但我想我只需要使用 $state.go() 即可导航到控制器并刷新整个视图...哦,好吧。
  • 多尝试一些时间......伙计......优化的解决方案总是更好,可能需要一些时间。

标签: javascript angularjs ionic-framework


【解决方案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() 的作用与您在链接函数中所做的相同,只是格式不同。

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

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

【讨论】:

  • 是的,没错。如果您可以添加一些示例代码,那将不胜感激,因为我不完全确定如何从使用链接功能切换到绑定。谢谢!
  • 添加了一些示例代码(未经测试,但应该像这样工作)
  • 太棒了!感谢那。我最终做的是将代码保留在链接函数中并在那里添加观察者,观察'params.currentIndex'(我必须观察范围对象的属性,而不是范围本身的属性)我已经更新了我的plunker 以反映更改。
【解决方案2】:

再试一次,

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();
  }

出现一个错误,但可以修复。我正在努力找出答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 2016-07-12
    • 1970-01-01
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多