ฉันจะตั้งชื่อรุ่นไดนามิกใน AngularJS ได้อย่างไร?


91

ฉันต้องการกรอกแบบฟอร์มด้วยคำถามแบบไดนามิก (ซอที่นี่ ):

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

ทุกอย่างใช้งานได้ยกเว้นแบบจำลองเป็นคำตอบ ["{{question.Name}}"] แทนคำตอบที่ประเมิน ["GenderQuestion"] ฉันจะตั้งชื่อรุ่นนั้นแบบไดนามิกได้อย่างไร?

คำตอบ:


121

http://jsfiddle.net/DrQ77/

คุณสามารถใส่นิพจน์จาวาสคริปต์ng-modelได้


1
ฉันสาบานว่าฉันพยายามแล้ว ขอบคุณมาก. ฉันไปเส้นทางอื่นและตั้งโมเดลเป็นคำถามคำตอบ (ฉันจะใส่ซอที่ปรับปรุงแล้วในอีกเล็กน้อย) ซึ่งกลายเป็นคำตอบที่ตรงกว่า (ต้องออกจากความคิดของ jQuery) แต่ เป็นเรื่องดีที่รู้ว่าฉันทำได้อย่างที่ฉันวางแผนไว้ในตอนแรก ขอบคุณอีกครั้ง!
Mike Pateras

ในกรณีนี้จะช่วยให้คนอื่นผมมีปัญหาที่คล้ายกัน แต่ปัญหาของผมก็คือว่าผมใช้เมื่อสิ่งที่ฉันต้องการจริงๆคือng-pattern="field.pattern" pattern="{{field.pattern}}"สร้างความสับสนว่าเชิงมุมมักจะให้ตัวช่วยสำหรับแอตทริบิวต์แบบไดนามิก แต่คราวนี้เขียนว่าเป็นการตรวจสอบความถูกต้องฝั่งไคลเอ็นต์ของตัวเองและตั้งชื่อเดียวกัน
colllin

ทำไมคุณถึงตัดสินใจสร้างวัตถุว่างเปล่า (คำตอบ) ในเมื่อคุณไม่มีจุดประสงค์ที่แท้จริง ดูเหมือนว่าคุณจะใช้มันเฉพาะใน ng-model เท่านั้นและนอกเหนือจากนี้ดูเหมือนจะไม่มีจุดประสงค์ใด ๆ ดังนั้นทำไมไม่ละเว้นมันโดยสิ้นเชิงและทำให้มันใช้งานได้ คุณช่วยชี้แจงได้ไหม?
Devner

ฉันเพิ่งพยายามทำการเปลี่ยนแปลงขั้นต่ำจากรหัสเดิม หากคุณดูรหัสที่แก้ไขแล้วของ Mike ( jsfiddle.net/2AwLM/23 ) เขาตัดสินใจที่จะกำจัดมัน

ขอบคุณมากสำหรับเรื่องนี้. ช่วยฉันได้มาก ดูที่นี่: stackoverflow.com/questions/34081903/…
Albert

31

คุณสามารถใช้สิ่งนี้scopeValue[field]ได้ แต่ถ้าฟิลด์ของคุณอยู่ในวัตถุอื่นคุณจะต้องมีโซลูชันอื่น

ในการแก้ไขสถานการณ์ทุกประเภทคุณสามารถใช้คำสั่งนี้:

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:

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

ทำงานได้ตามที่คาดไว้
C0ZEN

1
เย้! นี่คือสิ่งที่ฉันต้องการ! ขอขอบคุณ!
Snapman

2
ดี. แต่ยังคงหวังว่าเราจะสามารถใช้ได้ng-model="{{ variable }}":)
davidkonrad

13

สิ่งที่ฉันทำมีดังนี้:

ในตัวควบคุม:

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

ดังนั้นในเทมเพลตฉันสามารถใช้ชื่อแบบไดนามิกโดยสิ้นเชิงและไม่เพียง แต่อยู่ภายใต้องค์ประกอบที่กำหนดรหัสยาก (เช่นในกรณี "คำตอบ" ของคุณ):

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

หวังว่านี่จะช่วยได้


3

เพื่อให้คำตอบโดย @abourget สมบูรณ์ยิ่งขึ้นค่าของ scopeValue [field] ในโค้ดบรรทัดต่อไปนี้อาจไม่ได้กำหนดไว้ ซึ่งจะส่งผลให้เกิดข้อผิดพลาดเมื่อตั้งค่าฟิลด์ย่อย:

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

วิธีหนึ่งในการแก้ปัญหานี้คือการเพิ่มแอตทริบิวต์ ng-focus = "nullSafe (field)" ดังนั้นโค้ดของคุณจะมีลักษณะดังนี้:

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

จากนั้นคุณกำหนด nullSafe (ฟิลด์) ในคอนโทรลเลอร์ดังต่อไปนี้:

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

สิ่งนี้จะรับประกันได้ว่าไม่มีการกำหนด scopeValue [field] ก่อนที่จะตั้งค่าเป็น scopeValue [field] [subfield]

หมายเหตุ: คุณไม่สามารถใช้ ng-change = "nullSafe (field)" เพื่อให้ได้ผลลัพธ์เดียวกันเนื่องจาก ng-change เกิดขึ้นหลังจากที่มีการเปลี่ยนแปลง ng-model ซึ่งจะทำให้เกิดข้อผิดพลาดหากไม่ได้กำหนด scopeValue [field]


1

หรือคุณสามารถใช้

<select [(ngModel)]="Answers[''+question.Name+'']" ng-options="option for option in question.Options">
        </select>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.