How to pass JSON data to AngularJS directive

I am learning AngularJS. I am trying to create a reusable component.

Unfortunately, I am unable to pre-populate the fields inside the element with data received from JSON. I looked around and on the internet but couldn't solve it. Could you please let me know what I am doing wrong?

I have two controllers. A list of all countries is obtained:

app.controller('MainController', ['$scope', 'Countries',
                                  function ($scope, Countries) {
  $scope.countries = Countries.query();
}]);

      

Another collects a specific address:

app.controller('AddressesController', ['$scope', '$routeParams', 'Address',
  function($scope, $routeParams, Address) {

    if ($routeParams.addressId) {
      $scope.senderAddress = Address.get({addressId: $routeParams.addressId});
    } else {
      $scope.senderAddress = {"id":null, "country":null, "city":null, "street":null};
    }

    $scope.adData = {"id": 1, "country": "Poland", "city": "Warsaw", "street": "Nullowska 15"};
  }]);

      

Services are defined as follows: they work correctly and provide valid JSON:

myServices.factory('Countries', ['$resource',
                                function($resource) {
                                  return $resource('data/countries.json', {}, {
                                    query: {method:'GET'}
                                  })
                                }]);
myServices.factory('Address', ['$resource',
                               function($resource) {
                                 return $resource('data/:addressId.json', {}, {
                                   query: {method:'GET', params:{addressId:'addressId'}}
                                 })
                               }])

      

I have a routing set to route to AddressesController:

app.config(function ($routeProvider) {
  $routeProvider
  .when('/address', {
    templateUrl: 'partials/addresses.html',
    controller: 'AddressesController'
  })
  .when('/address/:addressId', {
    templateUrl: 'partials/addresses2.html',
    controller: 'AddressesController'
  })
});

      

Partial view is simple, I create 2 items

<label> Sender </label>
<address address-data='{{senderAddress}}'></address> <!-- I tried all combinations of passing this as argument -->

<label> Receiver </label>
<address></address>

      

The directive is now declared as:

app.directive("address", function () {
  return {
    restrict: "E",
    templateUrl: "/directives/address.html",
    scope: {addrData: '@senderAddress'},
    link: function(scope, element, attributes) {
      scope.adData = attributes["addressData"];
    }
  }
});

      

and a template for it:

<div> 

<label> {{senderAddress}} </label> <!-- senderAddress from Addresses Controller is filled correctly -->
<div>
    <label>Country</label>
    <select>
        <option value=""></option>
        <option ng-repeat="country in countries.countries" value="{{country}}">{{country}}</option>
    </select>
</div>

<div>
    <label>City {{dto.adData.city}}</label>
    <input type="text" data-ng-model="dto.adData.city"  /> <!-- this I cannot pre-fill -->
</div>

<div>
    <label>Street{{data.adData.city}}</label>
    <input type="text" data-ng-model="dto.adData.street"> <!-- this I cannot pre-fill -->
</div>

</div>

      

Everything works fine from the directive. But I will be missing something regarding how to handle scoping within a directive with data received from a JSON service. Is it because the JSON data is a promise object when referencing the directive? How to deal with this?

PS

I've also tried observing attributes:

link: function(scope, element, attributes) {
      //scope.dto.adData = attributes["addressData"];
      attrs.$observe('addressData', function(data) {
        if (!data)
          return;
        scope.dto.adData = data;
      })
    }

      

Even for statically defined data, this doesn't work:

app.directive("address", function () {
  return {

    controller: function($scope) {
      $scope.dto = {};
      $scope.dto.data = {"id": 1, "country": "Poland", "city": "Warsaw", "street": "Nullowska 15"};
    },

      

+3


source to share


2 answers


Passing in JSON like it is not, I would do it like it's kind of a hack in data binding and you probably don't get two way binding. I would use isolate the area .

Your directive will be used without rudders to bind the scope variable:

<address address-data='senderAddress'></address>

      

And then you would include an option scope

in the directive definition:



app.directive("address", function () {
  return {
    restrict: "E",
    templateUrl: "/directives/address.html",
    scope: {
        addressData: '='
    }
  }
});

      

The bare equal sign '='

tells Angular to bind the parent scope variable specified in the address-data attribute twice to the child scope's addressData variable. This is done automatically by normalizing the name "address-data" in the JD-style "addressData". If you want to name two scope variables differently, you can do it innerAddressData: '=addressData'

instead.

If you do it like this, you don't need the bind function at all, and the binding should still work.

+1


source


OK, I solved this, in case anyone has similar issues, this might help to check if the scope is set to true and check if JSON is parsed from the string; -).



app.directive("address", function () {
  return {
    restrict: "E",
    templateUrl: "/directives/address.html",
    scope: true, // creates its own local scope
    link: function(scope, element, attributes) {

      attributes.$observe('addressData', function(data) {
        if (!data)
          return;
        scope.dto = {};
        // works almost fine but in 2nd case data is also filled
        scope.dto.adData = angular.fromJson(data);

      })
    }
  }
});

      

0


source







All Articles