简体   繁体   中英

How to update ng-model with data from outer source?

Have the following question.

Consider we have the following HTML code:

<div id="container" ng-controller="Controller">
    <my-tag ng-model="values"></my-tag>
</div>

And the following controller:

var Controller = myApp.controller("Controller", function ($scope, $http, $filter, $q) {

    $scope.values = [];

    $http.get(someURLHere).then(function(response) {
        var data = JSON.parse(response.data);
        $scope.values = data;
    });

        /* And so on ... */

});

And here is the directive declaration:

myTag.directive('myTag', function() {
    return {
        require: "^ngModel",
        restrict: "E",
        replace: true,
        scope: {
            ngModel : "=",
        },
        controller: ['$scope', '$filter', myTagController],
        templateUrl: /* Here is a path to my template*/,        
        link: function (scope, elem, attrs, ctrl) {

            scope.data = scope.ngModel;         

        }
    }
});

The tag "my-tag" is my custom directive. It gets some data via ng-model and renders them. And the ng-controller="Controller" is some function which retrieves some data using AJAX and it suppose to write them into the $scope.values . After that I expect that they will be sent to my-tag via ng-model="values" . Next the data suppose to be rendered on the HTML page. But they don't! I do believe that my data have been retrieved correctly in Controller , but there is a problem with updating ng-model in my-tag . What is the best way to "send" data that have been retrieved in Controller to ng-model of my custom directive?

Update scope variables only in a $scope.apply().

Example for your code:

var Controller = myApp.controller("Controller", function ($scope, $http, $filter, $q) {

            $scope.values = [];

            /*
                Getting values via AJAX - assigned to ajaxvalues
            */  
           //still in callback from ajax:
            $scope.$apply(function() {
              $scope.values = ajaxvalues;
            });
           //... end callback
        });

See for details: http://docs.angularjs.org/api/ng .$rootScope.Scope

If your change on the data is not reflected in the view this is virtually every time because you do stuff outside of the AngularJS framework. This for example applies to event handlers and it applies to the callback of XMLHttpRequest . So I assume that you are using the latter function to get your data. You might want to check the $http service of AngularJS which will handle this correctly. In the callback you can then set the scope variable. But because AngularJS has this nice feature called promises, you could even do something like this:

$scope.values = $http.get('http://my.url/')
  .then(function(response){return response.data;});

This will actually bind the promise (which is to be resolved later) to $scope.values, but as AngularJS knows that this is a promise, it will not try to display it in any way. And when later the data arrives the .then function will be called which in this example just returnes the JSON data from the response. AngularJS will automatically handle this in the right way and put that JSON data into $scope.values then.

If you absolutely need or want to use something like XMLHttpRequest or have other code which is not triggered through AngularJS, you will need to make AngularJS aware that you are doing changes to the scope by wrapping the code into $scope.$apply() like this:

$scope.$apply(function(){
   $scope.values = response.data;
});

But you would probably be better off by using $http . some wrapper around it like Restangular or if necessary write your own wrapper. And if you do so try to make use of promises if it makes sense as it will make the code still easier and also reusable. Imagine this:

function makeRequest(id) {
  return $http.get('...some URL using id...')
     .then(function(response){return response.data;});
}

$scope.variable1 = makeRequest(1);
$scope.variable2 = makeRequest(5);
$scope.variable3 = makeRequest(7);

Clasically you would need complicated callback functions knowing where to put the data. Here your callback function does not need to care at all because AngularJS and its promises do all the magic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM