2012-09-23 13 views
82

Tôi muốn để cư một hình thức với một số câu hỏi động (fiddle here):Làm cách nào để đặt tên mô hình động trong AngularJS?

<div ng-app ng-controller="QuestionController"> 
    <ul ng-repeat="question in Questions"> 
     <li> 
      <div>{{question.Text}}</div> 
      <select ng-model="Answers['{{question.Name}}']" ng-options="option for option in question.Options"> 
      </select> 
     </li> 
    </ul> 

    <a ng-click="ShowAnswers()">Submit</a> 
</div> 
​ 
function QuestionController($scope) { 
    $scope.Answers = {}; 

    $scope.Questions = [ 
    { 
     "Text": "Gender?", 
     "Name": "GenderQuestion", 
     "Options": ["Male", "Female"]}, 
    { 
     "Text": "Favorite color?", 
     "Name": "ColorQuestion", 
     "Options": ["Red", "Blue", "Green"]} 
    ]; 

    $scope.ShowAnswers = function() 
    { 
     alert($scope.Answers["GenderQuestion"]); 
     alert($scope.Answers["{{question.Name}}"]); 
    }; 
}​ 

Tất cả mọi thứ hoạt động, ngoại trừ mô hình này là theo nghĩa đen câu trả lời [ "{{question.Name}}"], thay vì các câu trả lời được đánh giá ["GenderQuestion"]. Làm cách nào tôi có thể đặt tên mô hình đó theo cách động?

Trả lời

112

http://jsfiddle.net/DrQ77/

Bạn chỉ có thể đặt biểu javascript trong ng-model.

+1

Tôi thề tôi đã cố gắng đó. Cảm ơn nhiều. Tôi thực sự đã đi một con đường khác nhau, và chỉ cần thiết lập các mô hình để question.Answer (Tôi sẽ đưa ra một fiddle cập nhật trong một chút), mà hóa ra là một câu trả lời trực tiếp hơn (gotta ra khỏi suy nghĩ jQuery), nhưng thật tuyệt vời khi biết rằng tôi có thể thực sự làm theo cách mà tôi đã lên kế hoạch ban đầu cho tương lai. Cảm ơn một lần nữa! –

+5

Cập nhật fiddle: http://jsfiddle.net/2AwLM/23/ –

+0

Trong trường hợp điều này giúp bất kỳ ai khác, tôi đã gặp sự cố tương tự, nhưng vấn đề của tôi là tôi đã sử dụng 'ng-pattern =" field.pattern "' khi những gì tôi thực sự muốn là 'pattern =" {{field.pattern}} "'.Loại khó hiểu rằng góc thường cung cấp một trợ giúp cho các thuộc tính động nhưng lần này đã viết xác nhận phía máy khách của chính nó và đặt cho nó cùng một tên. – colllin

10

gì tôi đã kết thúc làm là một cái gì đó như thế này:

Trong bộ điều khiển:

link: function($scope, $element, $attr) { 
    $scope.scope = $scope; // or $scope.$parent, as needed 
    $scope.field = $attr.field = '_suffix'; 
    $scope.subfield = $attr.sub_node; 
    ... 

như vậy trong các mẫu tôi có thể sử dụng tên hoàn toàn năng động, và không chỉ dưới một yếu tố mã hóa cứng nhất định (như trong trường hợp "Câu trả lời" của bạn):

<textarea ng-model="scope[field][subfield]"></textarea> 

Hy vọng điều này sẽ hữu ích.

3

Để làm cho câu trả lời được cung cấp bởi @abourget hoàn chỉnh hơn, giá trị của scopeValue [field] trong dòng mã sau đây có thể không được xác định. Điều này sẽ dẫn đến một lỗi khi thiết lập trường con:

<textarea ng-model="scopeValue[field][subfield]"></textarea> 

Một cách để giải quyết vấn đề này là bằng cách thêm một thuộc tính ng lấy nét = "nullSafe (lĩnh vực)", do đó, mã của bạn sẽ trông giống như dưới đây:

<textarea ng-focus="nullSafe(field)" ng-model="scopeValue[field][subfield]"></textarea> 

sau đó, bạn xác định nullSafe (lĩnh vực) trong một bộ điều khiển giống như dưới đây:

$scope.nullSafe = function (field) { 
    if (!$scope.scopeValue[field]) { 
    $scope.scopeValue[field] = {}; 
    } 
}; 

Điều này sẽ đảm bảo rằng scopeValue [field] không phải là không xác định trước khi cài đặt bất kỳ giá trị cho scopeValue [trường] [trường con ].

Lưu ý: Bạn không thể sử dụng ng-thay đổi = "nullSafe (trường)" để đạt được kết quả tương tự vì ng-thay đổi xảy ra sau khi mô hình ng đã được thay đổi, sẽ ném lỗi nếu scopeValue [field] không định nghĩa được.

27

Bạn có thể sử dụng một cái gì đó như thế này scopeValue[field], nhưng nếu trường của bạn nằm trong đối tượng khác, bạn sẽ cần một giải pháp khác.

Để giải quyết tất cả các loại tình huống này, bạn có thể sử dụng chỉ thị này:

this.app.directive('dynamicModel', ['$compile', '$parse', function ($compile, $parse) { 
    return { 
     restrict: 'A', 
     terminal: true, 
     priority: 100000, 
     link: function (scope, elem) { 
      var name = $parse(elem.attr('dynamic-model'))(scope); 
      elem.removeAttr('dynamic-model'); 
      elem.attr('ng-model', name); 
      $compile(elem)(scope); 
     } 
    }; 
}]); 

Html dụ:

<input dynamic-model="'scopeValue.' + field" type="text"> 
+2

đã lưu ngày của tôi :) – WeMakeSoftware

+0

Hoạt động như mong đợi. – C0ZEN

+1

Yay! Đây là những gì tôi cần! Cảm ơn bạn! – Snapman

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