AngularJS directive does not update on scope variable changes
You should create a bound scope variable and watch its changes:
return {
restrict: 'E',
scope: {
name: '='
},
link: function(scope) {
scope.$watch('name', function() {
// all the code here...
});
}
};
How to update directive when a scope variable changes?
First remove the interpolation:
<!--REMOVE interpolation
<div ng-app="app" words="{{search.keywords}}">{{search.results}}</div>
-->
<div ng-app="app" words="search.keywords">{{search.results}}</div>
Then use a watcher:
angular.module('app', []).directive('words', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$watch(attrs.words, function(newValue) {
if (!newValue) return;
var words = newValue.split(' ');
for(var i=0; i<words.length; i++) {
var r = new RegExp(words[i], 'ig')
element.html(element.html().replace(r, '<span class="highlight">' + words[i] + '</span>'));
};
});
}
};
})
For more information, see AngularJS $rootScope.scope API Reference - $watch.
Angular $scope variable not updating
Actually this has been discussed in more links.
Don't use primitive type variable. Instead of that use object in scope.
For example,
Don't use like $scope.primitiveVariale
instead of this $scope.object={primitiveVariale:null}
So in view use like object.primitiveVariale
then this will be reflect in all the view. Please see the following links.
https://github.com/angular/angular.js/wiki/Understanding-Scopes
AngularJs: Why does scope inside my directive not update when async data arrives?
When Angular first runs your directive's controller function, your $scope.items === undefined
, so when you do this.items = $scope.items
, your this.items === undefined
too.
That's it. After that there is nothing that changes this.items
.
This is unlike $scope.items
. $scope.items
is two-way bound to the outer scope, so whenever Angular detects a change externally, it sets the isolated scope variable.
The easiest way (and most suitable, in my opinion) is to use the $scope
property directly in the directive:
<div>
Inside directive
<ul ng-repeat="i in items">
<li>{{ i }}</li>
</ul>
</div>
If you want to use your controller as ViewModel instead of scope (I don't know why you would), you could do:
$scope.$watchCollection("items", function(newVal, oldVal) {
ctrl.items = newVal;
});
EDIT:
In Angular 1.3 you can also do bindToController: true
in the directive's definition, so that the controller property "items
" will get the two-way binding that $scope.items
gets. Then, you don't even need to do this.items = $scope.items;
:
Your forked plunker to illustrate.
change directive when scope variable changes
You need to give the directive access to fields
by adding a binding for it:
scope: {
action: '@',
method: '@',
html: '=',
fields: '='
}
And HTML:
<dform fields="fields" ...
The value might be undefined
the first time, then you don't want to call dform
:
scope.$watch('fields', function(newValue, oldValue) {
if (newValue === oldValue) return;
var config = {
"html": newValue
};
elm.dform(config);
});
Update
With this HTML:
<div html="fields" dform></div>
You just need to watch html
instead, no need for $parent
or adding fields
as a binding:
scope.$watch('html', ...
AngularJs - directive not updating controller variable
You seems to be made a typo in Directive Definition Object, where $scope
should be scope
.
I'd like to suggest few things to improve your current approach, rather than using watcher
in parent controller method. You should pass a callback to directive and call it as soon as you're done with reader object loaded. Which turns out that your isolated scope will appear like below
restrict: 'A',
scope: {
callback: '&'
},
and then put new method inside controller where we will pass a file data to that method.
$scope.importData = function(data) {
DataManagementService.importData(newValue);
});
And then from element pass callback method correctly on directive
<input id="btnImport" type="file" es-file-read callback="importData(data)"/>
Call method from directive code correctly.
reader.onload = function (loadEvent) {
$scope.$apply(function () {
$scope.esFileRead= loadEvent.target.result;
$scope.callback({ item: $scope.esFileRead });
});
};
Related Topics
Javascript Innerhtml Not Updating Element
Rendering Mjpeg Stream in Html5
Getting an Array of Column Names At Sheetjs
How to Get Convert an Object to HTML Markup
Displaying Navbar on Multiple HTML Pages Using Bootstrap
How to Refresh the Data in a Jqgrid
How to Remove HTML Element from Dom With React
Datatables - Search in Multiple Columns With a Single Drop Down
Simple Pagination in JavaScript
Get Selected Item Value from Bootstrap Dropdown With Specific Id
How to Validate This Select Option If Not Selected
Uncaught Typeerror: (Intermediate Value)(...) Is Not a Function
How to Reset Child Elements' State
Javascript - Remove Milliseconds from Date Object
Number Value Format With Comma and Two Decimal Points
Preventing Viewport Resize of Web Page When Android Soft Keyboard Is Active
Prevent Html5 Videos from Downloading the Files on Mobile - Videojs