2014-08-28 138 views
3

我正在學習AngularJS。我嘗試創建一個可重用的組件。如何將JSON數據傳遞給AngularJS指令

不幸的是,我不能預先填充元素內的字段與從JSON獲得的數據。 我看了看SO和網頁,但無法解決它。你能不能讓我知道我做錯了什麼?

我有兩個控制器。一個得到所有國家的列表:

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

其他收集特定地址:

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"}; 
    }]); 

的服務定義如下,他們似乎正常工作,並提供正確的JSONs:

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'}} 
           }) 
           }]) 

我有路由設置,以便它指向AddressesController:

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

局部視圖很簡單,我創建了2個元素

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

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

現在該指令被聲明爲:

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

和模板是:

<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> 

的所有作品,遠在指令之外。但是我錯過了關於如何處理指令中的作用域,其中的數據是從JSON服務獲取的。是否因爲JSON數據是創建指令鏈接時的承諾對象?如何處理它?

PS

我也嘗試觀察屬性:

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

即使是靜態定義的數據它不工作:

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

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

回答

1

在這樣的JSON傳遞是不是我會做它,因爲它是在數據類型的黑客結合,你可能沒有得到雙向綁定。我會用isolate scope

你的指令將無把手使用,以範圍變量聯繫起來:

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

然後你會包括指令定義一個scope選項:

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

裸等號-sign '='告訴Angular將address-data屬性中引用的父範圍變量雙重綁定到子範圍變量addressData。這是通過將名稱「address-data」標準化爲JS風格的「addressData」來自動完成的。如果您想以不同的方式命名兩個範圍變量,則可以改爲使用innerAddressData: '=addressData'

如果你這樣做,你根本不需要鏈接功能,綁定仍然應該工作。

+0

非常感謝,這是一個優雅的解決方案。我只是想知道這個Angular Best Practices摘要:「總是讓用戶儘可能地使用表達式 ng-href和ng-src是支持{{}}的純文本屬性 使用$ attrs。$ observe(),因爲表達式是異步的並且可以改變「,是不是再觀察其價值所在? – wsk 2014-08-29 10:42:07

+0

我相信最好的做法是指你處理明文值的情況。這裏您使用的是JSON數據;除非你想在你的JSON中包含句柄表達式(這是我認爲的一個錯誤),我認爲這種最佳做法是不相關的。 觀察屬性可能取決於你想要做什麼。儘管如此,它只是一種單向約束。如果更改指令作用域內的數據,它將不會更改父作用域中的數據。 – 2014-08-29 15:45:33

0

OK,我解決了這個問題,在任何情況下,有類似的問題,它可能有助於檢查範圍是否設置爲true,並檢查是否從字符串解析JSON ;-)。

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); 

     }) 
    } 
    } 
}); 
相關問題