Bagaimana cara mengatur nama model dinamis di AngularJS?


91

Saya ingin mengisi formulir dengan beberapa pertanyaan dinamis (biola di sini ):

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

Semuanya bekerja, kecuali modelnya adalah Jawaban ["{{question.Name}}"], bukan Jawaban yang dievaluasi ["GenderQuestion"]. Bagaimana cara menyetel nama model itu secara dinamis?

Jawaban:


121

http://jsfiddle.net/DrQ77/

Anda cukup memasukkan ekspresi javascript ng-model.


1
Aku bersumpah aku mencobanya. Terima kasih banyak. Saya benar-benar pergi ke rute yang berbeda, dan hanya mengatur model ke pertanyaan. Jawab (saya akan mengeluarkan biola yang diperbarui sebentar lagi), yang ternyata menjadi jawaban yang lebih langsung (harus keluar dari pola pikir jQuery), tetapi Senang rasanya mengetahui bahwa saya memang bisa melakukannya dengan cara yang semula saya rencanakan untuk masa depan. Terima kasih lagi!
Mike Pateras

Jika ini membantu orang lain, saya mengalami masalah yang sama, tetapi masalah saya adalah bahwa saya menggunakan ng-pattern="field.pattern"ketika apa yang sebenarnya saya inginkan pattern="{{field.pattern}}". Agak membingungkan bahwa angular biasanya menyediakan penolong untuk atribut dinamis tetapi kali ini menulis validasi sisi kliennya sendiri dan memberinya nama yang sama.
colllin

Mengapa Anda memutuskan untuk membuat objek kosong (Jawaban) ketika Anda tidak memiliki tujuan sebenarnya untuk itu? Sepertinya Anda hanya menggunakannya di ng-model & selain itu, sepertinya tidak ada tujuan apa pun. Jadi mengapa tidak menghilangkannya sama sekali dan membuatnya berfungsi seperti itu? Bisakah Anda menjelaskan?
Devner

Saya hanya mencoba membuat perubahan minimum dari kode aslinya. Jika Anda melihat kode revisi Mike ( jsfiddle.net/2AwLM/23 ), dia memutuskan untuk menyingkirkannya.
Tosh

Terima kasih banyak untuk ini. Banyak membantu saya. Lihat di sini: stackoverflow.com/questions/34081903/…
Albert

31

Anda dapat menggunakan sesuatu seperti ini scopeValue[field], tetapi jika bidang Anda ada di objek lain, Anda memerlukan solusi lain.

Untuk mengatasi semua jenis situasi, Anda dapat menggunakan arahan ini:

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

Contoh HTML:

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

Bekerja seperti yang diharapkan.
C0ZEN

1
Yay! Inilah yang saya butuhkan! Terima kasih!
Snapman

2
Bagus. Tapi tetap berharap kita bisa menggunakan ng-model="{{ variable }}":)
davidkonrad

13

Apa yang akhirnya saya lakukan adalah seperti ini:

Di pengontrol:

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

jadi di template saya bisa menggunakan nama yang benar-benar dinamis, dan tidak hanya di bawah elemen hard-code tertentu (seperti dalam kasus "Answers"):

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

Semoga ini membantu.


3

Untuk membuat jawaban yang diberikan oleh @abourget lebih lengkap, nilai scopeValue [field] di baris kode berikut bisa tidak ditentukan. Ini akan menghasilkan kesalahan saat mengatur subbidang:

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

Salah satu cara untuk memecahkan masalah ini adalah dengan menambahkan atribut ng-focus = "nullSafe (field)", sehingga kode Anda akan terlihat seperti di bawah ini:

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

Kemudian Anda mendefinisikan nullSafe (field) dalam pengontrol seperti di bawah ini:

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

Ini akan menjamin bahwa scopeValue [bidang] tidak ditentukan sebelum menyetel nilai apa pun ke scopeValue [bidang] [subbidang].

Catatan: Anda tidak dapat menggunakan ng-change = "nullSafe (field)" untuk mendapatkan hasil yang sama karena ng-change terjadi setelah ng-model diubah, yang akan memunculkan kesalahan jika scopeValue [field] tidak ditentukan.


1

Atau Anda bisa menggunakan

<select [(ngModel)]="Answers[''+question.Name+'']" ng-options="option for option in question.Options">
        </select>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.