Reputation: 187
I want to use one-time binding in my view {{::vm.list}}. That's all working well and good. However on a button click I want vm.list to refresh.
I can't seem to figure out how to manually trigger vm.list to update. Perhaps one time binding is not the answer?
here is a jsfiddle boilerplate example: http://jsfiddle.net/KamelJabber/e4nexvay/2/
(function () {
var c1 = function Controller1() {
var vm = this;
var addCount = 1;
vm.list = [{
Id: 1,
Text: "Blue One"
}, {
Id: 2,
Text: "Blue Two"
}, {
Id: 3,
Text: "Blue Three"
}];
vm.AddnRefresh = function () {
vm.list.push({
Id: vm.list.length,
Text: "Add " + addCount
});
addCount++;
//force a refresh of vm.list
}
};
var app = angular.module('myApp', []);
app.controller('Controller1', c1);
})();
<style> </style> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="Controller1 as vm">
<p>
<input type="button" ng-click="vm.AddnRefresh();" value="Add" />
</p>
<div ng-repeat="l in ::vm.list">{{::l.Text}}</div>
<p></p>
<div>LOTS of other stuff going on causing digest updates so really don't want to update list unless "Add" is called"</div>
</div>
</div>
Upvotes: 11
Views: 3187
Reputation: 2239
Angular will re-render the view if the parent DOM element is re-created. You can use a combination of ng-if, scope variable and $timeout service to achieve this:
View:
<div ng-if="!vm.status.reqRefresh">
<div ng-repeat="l in ::vm.list">{{::l.Text}}</div>
</div>
Controller:
vm.status = {
reqRefresh : false
};
vm.AddnRefresh = function () {
vm.list.push({
Id : vm.list.length,
Text : "Add " + addCount
});
addCount++;
//force a refresh of vm.list
vm.status.reqRefresh = true;
$timeout(function () {
vm.status.reqRefresh = false;
});
}
See updated fiddle here: http://jsfiddle.net/karank007/e4nexvay/143/
Upvotes: 3
Reputation:
I'm late to the party but I'll pitch in nevertheless.
I've been working on a notifier module for some time now and it's finally reached a 1.0.0 state where I feel I can start recommending it.
You could use this in two ways;
$broadcast
events manually to refresh a one-time binding. I reckon #2 would be the best way to fulfill what you're looking for and that would go something like this:
<input type="button" ng-click="vm.AddnRefresh();" value="Add" />
<div ng-repeat="l in :refresh:vm.list">
{{::l.Text}}
</div>
Notice the refresh
that's been added between your one-time colons. This is the key
you will utilise when wanting to trigger a refresh of the data.
All you need to do now is to update the AddnRefresh
method like so:
vm.addnRefresh = function () {
/** original implementation **/
$scope.$broadcast('$$rebind::refresh'); // where 'refresh' is the key used in the view.
};
$$rebind::
is the internal event namespace used by angular-bind-notifier.
And there you go - your view is now updated.
Here's a jsBin showcasing both ways of updating (1 $watcher & manual $broadcast).
Upvotes: 5
Reputation: 364
Hay you have to use the $scope
to see the updated view. I've just added the vm
in to a Scope. Here is the code:
(function () {
var c1 = function Controller1($scope) {
$scope.vm = this;
var addCount = 1;
$scope.vm.list = [{
Id: 1,
Text: "Blue One"
}, {
Id: 2,
Text: "Blue Two"
}, {
Id: 3,
Text: "Blue Three"
}];
$scope.vm.AddnRefresh = function () {
$scope.vm.list.push({
Id: $scope.vm.list.length,
Text: "Add " + addCount
});
addCount++;
//force a refresh of vm.list
}
};
var app = angular.module('myApp', []);
app.controller('Controller1', c1);
})();
You also have to remove the ::
:
<div ng-app="myApp">
<div ng-controller="Controller1 as vm">
<p>
<input type="button" ng-click="vm.AddnRefresh();" value="Add" />
</p>
<div ng-repeat="l in vm.list">{{::l.Text}}</div>
<p></p>
<div>LOTS of other stuff going on causing digest updates so really don't want to update list unless "Add" is called"</div>
</div>
</div>
Upvotes: -1