Кутове оновлення директиви при зміні параметрів


75

У мене є директива angular, яка ініціалізується так:

<conversation style="height:300px" type="convo" type-id="{{some_prop}}"></conversation>

Я хотів би, щоб він був достатньо розумним, щоб оновити директиву під час $scope.some_propзмін, оскільки це означає, що він повинен відображати зовсім інший вміст.

Я протестував його таким, який він є, і нічого не відбувається, функція зв’язування навіть не викликається при $scope.some_propзміні. Чи є спосіб зробити це?

Відповіді:


97

Функція посилання викликається лише один раз, тому вона не буде безпосередньо робити те, що ви очікуєте. Вам потрібно використовувати angular $watchдля перегляду змінної моделі.

Цей годинник потрібно налаштувати у функції посилання.

Якщо ви використовуєте ізольовану область для директиви, тоді область буде

scope :{typeId:'@' }

У свою функцію посилання ви додаєте годинник, як

link: function(scope, element, attrs) {
    scope.$watch("typeId",function(newValue,oldValue) {
        //This gets called when data changes.
    });
 }

Якщо ви не використовуєте ізольований приціл, використовуйте годинник some_prop


7
Я працюю над подібною проблемою, як OP. Документи AngularJS передбачають, що використання =in scope:створює двостороннє прив'язку, тобто зміни дочірньої області дії поширюються до батьківської області і навпаки - це не так? Мені потрібно вміти сказати директиві, щоб оновити себе з батьківського контролера.
Іно,

@Eno Ви це зрозуміли? Дійсно мене бентежить!
JMK

@JMK Я знайшов ці статті корисними для читання: undefinednull.com/2014/02/11/… github.com/angular/angular.js/wiki/Understanding-Scopes
Іно

Чи шкідливо мати область застосування 10000+ директив, яка запускає область дії. $ Watch, щоб прослухати bool для оновлення?
Леон Пелтьє,

Я виявив, що якщо параметр використовує '=', наведене вище рішення не працює, і я розслідую це.
Міккі

38

Що ви намагаєтеся зробити, це відстежувати властивість атрибута в директиві. Ви можете спостерігати за властивістю змін атрибутів за допомогою $ obser () наступним чином:

angular.module('myApp').directive('conversation', function() {
  return {
    restrict: 'E',
    replace: true,
    compile: function(tElement, attr) {
      attr.$observe('typeId', function(data) {
            console.log("Updated data ", data);
      }, true);

    }
  };
});

Майте на увазі, що я використовував функцію 'compile' у директиві тут, тому що ви не згадали, чи є у вас моделі, і чи це впливає на продуктивність.

Якщо у вас є моделі, вам потрібно змінити функцію " компіляції " на " посилання " або використовувати " контролер ", а для відстеження властивостей змін моделі слід використовувати $ watch () і взяти кутовий {{}} дужки з властивості, приклад:

<conversation style="height:300px" type="convo" type-id="some_prop"></conversation>

І в директиві:

angular.module('myApp').directive('conversation', function() {
  return {
    scope: {
      typeId: '=',
    },
    link: function(scope, elm, attr) {

      scope.$watch('typeId', function(newValue, oldValue) {
          if (newValue !== oldValue) {
            // You actions here
            console.log("I got the new value! ", newValue);
          }
      }, true);

    }
  };
});

1

Я сподіваюся, це допоможе перезавантажити / оновити директиву щодо значення з батьківської області

<html>

        <head>
            <!-- version 1.4.5 -->
            <script src="angular.js"></script>
        </head>

        <body ng-app="app" ng-controller="Ctrl">

            <my-test reload-on="update"></my-test><br>
            <button ng-click="update = update+1;">update {{update}}</button>
        </body>
        <script>
            var app = angular.module('app', [])
            app.controller('Ctrl', function($scope) {

                $scope.update = 0;
            });
            app.directive('myTest', function() {
                return {
                    restrict: 'AE',
                    scope: {
                        reloadOn: '='
                    },
                    controller: function($scope) {
                        $scope.$watch('reloadOn', function(newVal, oldVal) {
                            //  all directive code here
                            console.log("Reloaded successfully......" + $scope.reloadOn);
                        });
                    },
                    template: '<span>  {{reloadOn}} </span>'
                }
            });
        </script>


   </html>

0
angular.module('app').directive('conversation', function() {
    return {
        restrict: 'E',
        link: function ($scope, $elm, $attr) {
            $scope.$watch("some_prop", function (newValue, oldValue) {
                  var typeId = $attr.type-id;
                  // Your logic.
            });
        }
    };
}

0

Якщо ви користуєтесь AngularJS 1.5.3 або новішою, вам слід подумати про перехід до компонентів замість директив. Це працює дуже схоже на директиви, але з деякими дуже корисними додатковими можливостями, такими як $ onChanges (changesObj), один із гачків життєвого циклу, який буде викликаний щоразу, коли односторонні прив'язки оновлюються.

app.component('conversation ', {
    bindings: {
    type: '@',
    typeId: '='
    },
    controller: function() {
        this.$onChanges = function(changes) {
            // check if your specific property has changed
            // that because $onChanges is fired whenever each property is changed from you parent ctrl
            if(!!changes.typeId){
                refreshYourComponent();
            }
        };
    },
    templateUrl: 'conversation .html'
});

Ось документи для поглиблення на компоненти.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.