基于AngularJs中的一个指令属性的更改更新UI

时间:2022-11-24 19:48:22

I am struggling with data binding in AngularJs.

我正在和AngularJs中的数据绑定做斗争。

I have the following piece of markup in .html file that includes the custom directive:

我在.html文件中有如下标记,其中包含自定义指令:

<my-directive ng-repeat="i in object" attr-1="{{i.some_variable}}"></my-directive>

Note: 'some-variable' is being updated every 10 seconds(based on the associate collection and passed to template through controller).

注意:“some-variable”每10秒更新一次(基于关联集合并通过控制器传递给template)。

The directive's code includes:

该指令的代码包括:

myApp.directive('myDirective', function () {

  scope: {
   'attr-1': '=attr1'

which throws this exception because of the brackets in attr-1(see html code above).

由于attr1中的括号(参见上面的html代码),引发了这个异常。

It works though if I use read-only access(note at sign below):

如果我使用只读访问(请注意下面的符号):

myApp.directive('myDirective', function () {

  scope: {
   'attr-1': '@attr1'

I use scope.attr-1 in directive's HTML to show its value.

我使用范围。在指令的HTML中显示它的值。

The problem is that with read-only access UI is not reflecting the change in attribute change.

问题是,使用只读访问UI并不反映属性更改中的更改。

I've found solution with $parse or $eval(couldn't make them work tho). Is there a better one there?

我找到了$parse或$eval的解决方案(无法让它们工作)。有更好的吗?

2 个解决方案

#1


3  

You'll need only two-way binding and I think $parse or $eval is not needed.

您只需要双向绑定,我认为不需要$parse或$eval。

Please have a look at the demo below or in this fiddle.

请看看下面的演示或在这个小提琴。

It uses $interval to simulate your updating but the update can also come from other sources e.g. web socket or ajax request.

它使用$interval来模拟更新,但是更新也可以来自其他来源,例如web套接字或ajax请求。

I'm using controllerAs and bindToController syntax (AngularJs version 1.4 or newer required) but the same is also possible with just an isolated scope. See guide in angular docs.

我正在使用controllerAs和bindToController语法(AngularJs版本1.4或更新的required),但仅在一个独立的范围内也可以实现相同的功能。请参阅《角文档指南》。

The $watch in the controller of the directive is only to show how the directive can detect that the data have changed.

该指令的控制器中的$watch只是用来显示该指令如何检测数据发生了变化。

angular.module('demoApp', [])
	.controller('MainController', MainController)
	.directive('myDirective', myDirective);

function MainController($interval) {
	var self = this,
        refreshTime = 1000; //interval time in ms
    
    activate();
    
    function activate() {
    	this.data = 0;
    	$interval(updateView, refreshTime);
    }
    
    function updateView() {
    	self.data = Math.round(Math.random()*100, 0);
    }
}

function myDirective() {
	return {
    	restrict: 'E',
        scope: {
        },
        bindToController: {
            data: '='
        },
        template: '<div><p>directive data: {{directiveCtrl.data}}</p></div>',
        controller: function($scope) {
            $scope.$watch('directiveCtrl.data', function(newValue) {
            	console.log('data changed', newValue);
            });
        },
        controllerAs: 'directiveCtrl'
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.js"></script>
<div ng-app="demoApp" ng-controller="MainController as ctrl">
    model value in ctrl. {{ctrl.data}}
    <my-directive data="ctrl.data"></my-directive>
</div>

#2


0  

I've come to the following solution(in case somebody runs into the the same problem):

我想到了下面的解决方案(万一有人遇到同样的问题):

// Directive's code

myApp.directive('myDir', function () { return {
    restrict: 'E',

    templateUrl: function () {
        return 'my-dir.html';
    },
    scope: {
        'id': '@arId',
        'x': '@arX',
        'y': '@arY',
        //....
    },
    link: function ($scope, element, attrs) {

         // *** SOLUTION ***
         attrs.$observe('arId', function (id) {
             $scope.id = id;
         });
         //...
    }

Update: somebody sent me this answer, they have the same problem and came up with a very similar if not exact same solution:

更新:有人给我发了这个答案,他们有同样的问题,并提出了一个非常相似的,如果不是完全相同的解决方案:

Using a directive inside an ng-repeat, and a mysterious power of scope '@'

在ng-repeat中使用指令,以及范围的神秘力量“@”

It is useful to read because they explain what's the idea behind it.

这是很有用的,因为他们解释了背后的想法。

#1


3  

You'll need only two-way binding and I think $parse or $eval is not needed.

您只需要双向绑定,我认为不需要$parse或$eval。

Please have a look at the demo below or in this fiddle.

请看看下面的演示或在这个小提琴。

It uses $interval to simulate your updating but the update can also come from other sources e.g. web socket or ajax request.

它使用$interval来模拟更新,但是更新也可以来自其他来源,例如web套接字或ajax请求。

I'm using controllerAs and bindToController syntax (AngularJs version 1.4 or newer required) but the same is also possible with just an isolated scope. See guide in angular docs.

我正在使用controllerAs和bindToController语法(AngularJs版本1.4或更新的required),但仅在一个独立的范围内也可以实现相同的功能。请参阅《角文档指南》。

The $watch in the controller of the directive is only to show how the directive can detect that the data have changed.

该指令的控制器中的$watch只是用来显示该指令如何检测数据发生了变化。

angular.module('demoApp', [])
	.controller('MainController', MainController)
	.directive('myDirective', myDirective);

function MainController($interval) {
	var self = this,
        refreshTime = 1000; //interval time in ms
    
    activate();
    
    function activate() {
    	this.data = 0;
    	$interval(updateView, refreshTime);
    }
    
    function updateView() {
    	self.data = Math.round(Math.random()*100, 0);
    }
}

function myDirective() {
	return {
    	restrict: 'E',
        scope: {
        },
        bindToController: {
            data: '='
        },
        template: '<div><p>directive data: {{directiveCtrl.data}}</p></div>',
        controller: function($scope) {
            $scope.$watch('directiveCtrl.data', function(newValue) {
            	console.log('data changed', newValue);
            });
        },
        controllerAs: 'directiveCtrl'
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.js"></script>
<div ng-app="demoApp" ng-controller="MainController as ctrl">
    model value in ctrl. {{ctrl.data}}
    <my-directive data="ctrl.data"></my-directive>
</div>

#2


0  

I've come to the following solution(in case somebody runs into the the same problem):

我想到了下面的解决方案(万一有人遇到同样的问题):

// Directive's code

myApp.directive('myDir', function () { return {
    restrict: 'E',

    templateUrl: function () {
        return 'my-dir.html';
    },
    scope: {
        'id': '@arId',
        'x': '@arX',
        'y': '@arY',
        //....
    },
    link: function ($scope, element, attrs) {

         // *** SOLUTION ***
         attrs.$observe('arId', function (id) {
             $scope.id = id;
         });
         //...
    }

Update: somebody sent me this answer, they have the same problem and came up with a very similar if not exact same solution:

更新:有人给我发了这个答案,他们有同样的问题,并提出了一个非常相似的,如果不是完全相同的解决方案:

Using a directive inside an ng-repeat, and a mysterious power of scope '@'

在ng-repeat中使用指令,以及范围的神秘力量“@”

It is useful to read because they explain what's the idea behind it.

这是很有用的,因为他们解释了背后的想法。