Làm cách nào để đặt tên mô hình động trong AngularJS?


91

Tôi muốn điền vào biểu mẫu một số câu hỏi động (giải đáp tại đây ):

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

Mọi thứ đều hoạt động, ngoại trừ mô hình theo nghĩa đen là 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 động tên mô hình đó?

Câu trả lời:


121

http://jsfiddle.net/DrQ77/

Bạn chỉ cần đặt biểu thức javascript vào ng-model.


1
Tôi thề là tôi đã thử điều đó. Cảm ơn rât nhiều. Tôi thực sự đã đi một con đường khác và chỉ cần đặt mô hình là câu hỏi. thật tuyệt khi biết rằng tôi thực sự có thể 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!
Mike Pateras

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

Tại sao bạn quyết định tạo một đối tượng trống (Câu trả lời) khi bạn không có mục đích thực sự cho nó? Bạn dường như chỉ sử dụng nó trong ng-model & khác với điều này, dường như không có bất kỳ mục đích nào. Ông có thể làm rõ?
Devner

Tôi chỉ cố gắng thực hiện một thay đổi tối thiểu so với mã gốc. Nếu bạn nhìn vào mã đã sửa đổi của Mike ( jsfiddle.net/2AwLM/23 ), anh ấy đã quyết định loại bỏ nó.
Tosh

Cám ơn bạn rất nhiều về điều này. Đã giúp tôi rất nhiều. Xem tại đây: stackoverflow.com/questions/34081903/…
Albert

31

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 một đố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, 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);
        }
    };
}]);

Ví dụ về html:

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

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

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

2
Đẹp. Nhưng vẫn muốn chúng ta chỉ có thể sử dụng ng-model="{{ variable }}":)
davidkonrad

13

Những gì tôi đã 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;
  ...

vì vậy, trong các mẫu, tôi có thể sử dụng các tên động hoàn toàn và không chỉ dưới một phần tử được 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>

Hi vọng điêu nay co ich.


3

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

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

Một cách để giải quyết vấn đề này là thêm một thuộc tính ng-focus = "nullSafe (field)", vì vậy mã của bạn sẽ giống như bên dưới:

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

Sau đó, bạn xác định nullSafe (trường) trong bộ điều khiển như bên dưới:

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

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

Lưu ý: Bạn không thể sử dụng ng-change = "nullSafe (field)" để đạt được kết quả tương tự vì ng-change xảy ra sau khi ng-model đã được thay đổi, điều này sẽ gây ra lỗi nếu scopeValue [field] không được xác định.


1

Hoặc bạn có thể sử dụng

<select [(ngModel)]="Answers[''+question.Name+'']" ng-options="option for option in question.Options">
        </select>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.