2013-03-10 40 views
19

Tôi gặp sự cố khi cài đặt mục đã chọn trong chỉ thị chọn góc. Tôi không biết đây có phải là lỗi hay thiết kế có ý thức từ các nhà thiết kế góc cạnh hay không. Nó chắc chắn làm cho các chỉ thị chọn rất ít hữu ích mặc dù.Đặt mục đã chọn trong angularJS chọn chỉ thị

Mô tả:

Ứng dụng của tôi giao tiếp với API REST để nhận thực thể từ cơ sở dữ liệu. API chỉ ra rằng quan hệ của đối tượng được gửi với thuộc tính ID chỉ để bạn có thể truy xuất chúng trong các yêu cầu tiếp theo nếu cần.

Ví dụ:

{ id : 1, customerName : "some name", city : {id : 12}} 

nơi thành phố là một thực thể có thể được lấy ra thông qua một thiết bị đầu cuối REST của khác nhau bằng cách sử dụng id thành phố và trông giống như vậy:

{ id: 12, name : "New York"} 

tôi cần phải tạo ra một hình thức để chỉnh sửa thực thể khách hàng bằng menu thả xuống với tất cả các thành phố có thể để người dùng có thể chọn thành phố thích hợp từ danh sách. Danh sách ban đầu phải hiển thị thành phố của khách hàng khi được truy xuất từ ​​đối tượng JSON.

Các hình thức trông như thế này:

<form> 
    <input type="text" ng-model="customer.name"/> 
    <select ng-model="customer.city" ng-options="i as i.name for i in cities"></select> 
</form> 

Và bộ điều khiển trông như thế này:

app.controller('MainCtrl', function ($scope, $http) { 
    $http.get(serviceurl + 'admin/rest/customer/' + id + "/", { 
     params: {"accept": "json"}, 
     withCredentials: true 
    }).then(function (response) { 
       $scope.customer = response.data.item; 
      }); 
    $http.get(serviceurl + 'admin/rest/city/', { 
     params: {"accept": "json"}, 
     withCredentials: true 
    }).then(function (response) { 
       $scope.cities = response.data.items; 
       // THIS LINE LOADS THE ACTUAL DATA FROM JSON 
       $scope.customer.city = $scope.findCity($scope.customer.city); 
      }); 
    $scope.findCity = function (city) { 
     for (var i = 0; i < $scope.cities.length; i++) { 
      if ($scope.cities[i].id == city.id) { 
       return $scope.cities[i]; 
      } 
     } 
    } 
}); 

gì nên xảy ra: một lần đầy đủ các chi tiết của đối tượng thành phố được nạp chỉ thị chọn phải đặt thành phố đã được tải dưới dạng mục đã chọn trong danh sách.

Điều gì xảy ra: danh sách hiển thị một mục trống và không có cách nào để khởi tạo mục đã chọn nếu mục đã chọn từ các đối tượng bên ngoài mảng mục.

DEMO của vấn đề ở đây: http://plnkr.co/edit/NavukDb34mjjnQOP4HE9?p=preview

Có một giải pháp cho việc này? Mục được chọn có được đặt theo chương trình theo cách chung chung sao cho các cuộc gọi AJAX và logic được chọn được cấu trúc lại thành một widget chọn dựa trên AJAX có thể tái sử dụng được không?

Trả lời

21

Lý do nó không hoạt động là góc cạnh mong đợi các đối tượng tham chiếu bằng nhau. Trong trường hợp của bạn ('chọn từ đối tượng' trong plnkr của bạn) tạo ra một đối tượng mới, mặc dù với các thuộc tính giống nhau. Tuy nhiên, Angular không thể biết rằng hai đối tượng khác nhau đại diện cho cùng một đối tượng. Bạn có ít nhất hai phương pháp:

Tìm các trường hợp đối tượng đúng thành phố

Thay vì đặt $scope.customer.city đến một đối tượng mới, tìm đối tượng thành phố thực tế từ các mảng $scope.cities. Nếu bạn đang sử dụng UnderscoreJs bạn có thể làm một cái gì đó như:

$scope.customer.city = _.find($scope.cities, function (city) { 
    return city.id === theCustomersCity.id; 
}); 

Bind to id thành phố thay vì đối tượng thành phố

cách tiếp cận khác, mà có thể được dễ dàng hơn, là thay đổi ng-modelng-options chỉ thị để khớp với id thay vì đối tượng.Xem ví dụ làm việc here.

<select ng-model="customer.cityId" ng-options="i.id as i.name for i in cities"></select> 
+0

Thực tế tôi tìm thấy thành phố chính xác: $ scope.customer.city = $ scope.findCity ($ scope.customer.city); Bất kỳ ý tưởng nào về lý do mã của bạn hoạt động, nơi tôi bị lỗi? – javito

+0

Nó có thể là một điều kiện chủng tộc mà cuộc gọi ajax thứ hai của bạn ('admin/rest/city /') được hoàn thành trước khi đầu tiên (''admin/rest/customer /' + id') không? – Martin

+0

Tôi đã sử dụng cách tiếp cận với id và vấn đề của tôi liên quan đến việc gửi một chuỗi thay vì một số nguyên – Juan

-1

http://plnkr.co/edit/Lw8uadPf4G5KYXLzeaHb cho thấy rằng nếu bạn đặt đối tượng tham chiếu đến phạm vi của bạn thì nó hoạt động. đó chỉ là câu trả lời thứ ba hơi khác với Martins

2

Tôi đã gặp phải vấn đề tương tự. Các tùy chọn của tôi và dữ liệu được mô hình hóa đều đến từ các cuộc gọi API riêng biệt.

Thay vì thêm một lớp vô hướng bằng cách sử dụng ng-model trên các khóa đối tượng, tôi đã kết thúc bằng văn bản một chỉ thị đơn giản sử dụng biến "proxy".

<select ng-model="customer.city" ng-options="i as i.name for i in cities"></select> 

trở thành

<select ng-model="customer_cityProxy" ng-options="i.name as i.name for i in cities"></select> 

Sử dụng $ xem trên customer.city và customer_cityProxy, tôi nhận được hành vi mong đợi.

Vẫn còn một vài hạn chế, vì nó chỉ hoạt động nếu các phím bị ngắt.

Mã có sẵn ở đây: https://github.com/gosusnp/options-proxy

41

Nó cũng đơn giản như thế này

<select 
    ng-model="item" 
    ng-options="item.name for item in items track by item.name"> 

Sau đó bên trong bạn điều khiển:

// all items 
$scope.items = [{name: 'a'}, {name: 'b'}, {name: 'c'}]; 
// set the active one 
$scope.item = {name: 'b'}; 
// or just 
$scope.item = $scope.items[1] 

Khám phá http://docs.angularjs.org/api/ng.directive:select Từ đó:

trackexpr: Được sử dụng khi làm việc với một mảng của các đối tượng. Kết quả của biểu thức này sẽ được sử dụng để xác định các đối tượng trong mảng. Trackexpr rất có thể sẽ tham chiếu đến biến giá trị (ví dụ: value.propertyName).

Phần còn lại chỉ gán giá trị cho biến số $scope.item và góc sẽ xác định yếu tố nào sẽ được đặt làm hoạt động bằng cách kiểm tra thuộc tính name của mục.

+0

Điều này có vẻ là câu trả lời hay nhất - 'trackexpr' là tại địa chỉ – Pakman

+0

Tại sao không được chấp nhận làm câu trả lời? Tôi nghĩ rằng nó sẽ tiết kiệm rất nhiều thời gian cho mọi người. – hutingung

+0

+1 cho hầu hết các câu trả lời thanh lịch! Không biết về biểu thức 'theo dõi'. Câu trả lời này phải được chấp nhận. –

Các vấn đề liên quan