I was wondering if possible, using angular one time binding, to completely re-render the view/template after a model update, also by recompiling the template. For instance, on a button press, maybe in the way react works: I update the model and explicitly force to update the view. Basically here is what I am trying to achieve:
// controller
angular.module('app', []).controller('AppCtrl', function($scope) {
$scope.items = [
{id: 1},
{id: 2},
{id: 3}
];
$scope.addAndRefresh = function() {
$scope.items.push({id: 4});
// manually call render logic here???
};
});
<!-- HTML template -->
<div ng-repeat="item in ::items">
{{item.id}}
</div>
<button ng-click="addAndRefresh()">Add</button>
By clicking on the "Add" button I would like to refresh the view to see the newly added item.
I was trying to figure out some way to do this elegantly as well. I wish there was something built into the framework to refresh one-time bindings. All I came up with is using ngIf to remove the element I wanted to refresh and the add it back.
Here's a demo. Click the Add Item button, you'll see that the list does not refresh due to the one-time binding on the repeat. Check the refresh values and click again, and the items will be updated:
var app = angular.module('demo', []);
app.controller('RefreshCtrl', function($scope, $timeout) {
var counter = 4;
$scope.visible = true;
$scope.items = ['Item1', 'Item2', 'Item3'];
$scope.addItem = function() {
if ($scope.refresh) {
$scope.visible = false;
}
$scope.items.push('Item' + counter);
counter++;
$timeout(function() {
$scope.visible = true;
});
};
});
<script src="https://code.angularjs.org/1.3.17/angular.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<div ng-app="demo" ng-controller="RefreshCtrl" class="container">
<button class="btn btn-default" ng-click="addItem()">Add Item</button>
<input type="checkbox" ng-model="refresh" />Refresh Values
<div ng-if="visible">
<h3 ng-repeat="item in ::items">{{item}}</h3>
</div>
<p>Items Array: {{items}}</p>
</div>
Depending on what you are after, I would recommend one of two solutions:
I'm the author of the former, and the big difference between it and other solutions is the choice of hooking into the $parse
service.
As such, you can use the introduced {{:refreshkey:expression}}
/:refreshkey:expression
syntax in most (if not all) areas of Angular where an expression is accepted.
js
angular.module('app', []).controller('AppCtrl', function($scope) {
$scope.items = [
{id: 1},
{id: 2},
{id: 3}
];
$scope.addAndRefresh = function() {
$scope.items.push({id: 4});
/**
* '$$rebind' is the internal namespace used by angular-bind-notifier.
* 'refresh' is the refresh key used in your view.
*/
$scope.$broadcast('$$rebind:refresh');
};
});
markup
<!-- HTML template -->
<div ng-repeat="item in :refresh:items">
{{::item.id}}
</div>
<button ng-click="addAndRefresh()">Add</button>
js
angular.module('app', []).controller('AppCtrl', function($scope) {
$scope.items = [
{id: 1},
{id: 2},
{id: 3}
];
$scope.add = function() {
$scope.items.push({id: 4});
};
});
markup
<!-- HTML template -->
<div bind-notifier="{ refresh: items.length }">
<div ng-repeat="item in :refresh:items">
{{::item.id}}
</div>
</div>
<button ng-click="add()">Add</button>
Check out the README and this jsBin for some usage examples.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With