0

階層JSONデータをビューに正常にバインドしています。ただし、knockout.mappingを使用して同じJSONデータをビューモデルに投影すると、foreach関数は子配列を反復処理しません。

viewModelデータにバインドするとき、子データ(Answers)が存在することを知っています。これは、を使用してオブジェクト参照を表示できるためです。

ビュー:

<div data-bind="foreach: $data">
    <p data-bind="html: QuestionText">

    <!-- this section outputs [object Object] when bound to pageViewModel or Json -->
    <p data-bind="html: Answers">

        <!-- RadioButtonSelection-->
        <div data-bind="if: QuestionSelectionMode == 'RadioButtonSelection'">
            <span data-bind="foreach: $data.Answers">
                <input type="radio" data-bind="attr: {name: $parent.QuestionId}, value: AnswerId" /><span data-bind="text: AnswerText"></span>
            </span>
        </div>

        <!-- CheckBoxSelection-->
        <div data-bind="if: QuestionSelectionMode == 'CheckBoxSelection'">
            <span data-bind="foreach: $data.Answers">
                <div><input type="checkbox" data-bind="value: AnswerId"/><span data-bind="text: AnswerText"></span></div>
            </span>
        </div>

        <!-- DropDownListSelection-->
        <div data-bind="if: QuestionSelectionMode == 'DropDownListSelection'">
            <select data-bind="options: $data.Answers, optionsText: 'AnswerText', optionsValue: 'AnswerId'"></select>
        </div>

    </p>
</div>

ViewModelコード:

<script type="text/javascript">

    /* get the first page of questions and bind them */
    @{ 

        string startUrl = "URL-Removed" + ViewData["formId"] + "?page=" + ViewData["pageNumber"];

    }

    var pageViewModel;


    $.ajax({ url: '@startUrl' ,
        async: false,
        dataType: 'json',
        success: function (data) {
            //console.log("JSON received:  " + JSON.stringify(data));            

            // when i bind to the view model the parent question text shows, but not the child answers
            pageViewModel = ko.mapping.fromJS(data);
            ko.applyBindings(pageViewModel);
            //ko.applyBindings(data);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log("Error: TextStatus: " + textStatus + " errorThrown: " + errorThrown);
        }
    });
    </script>

そして、JSONのデータの一部を次に示します。

 [{"FormId":0,"QuestionId":28807,"QuestionSelectionMode":"StaticTextSelection","QuestionText":"<hr />\r\n<div><span style=\"font-size: medium\"><span style=\"color: #003366\"><strong>Event Details</strong></span></span></div>","DisplayOrder":1,"PageNumber":1,"Answers":[]},{"FormId":0,"QuestionId":28782,"QuestionSelectionMode":"RadioButtonSelection","QuestionText":"<div><span style=\"font-size: larger\"><strong>What type of patient safety event is being reported?</strong></span><span style=\"font-size: x-small\"><strong>&nbsp; </strong><font color=\"#ff0000\" size=\"1\">(Required)</font></span></div>","DisplayOrder":2,"PageNumber":1,"Answers":[{"AnswerId":460935,"QuestionId":0,"AnswerTypeId":null,"RegularExpressionId":null,"AnswerText":"Reached the patient","DisplayOrder":1,"Selected":null,"DefaultText":null,"Mandatory":null,"ValidatorId":null,"SyncRefMandatory":null,"FieldLength":null,"AnswerFormId":null,"EntryMaskId":null,"ShowTimeSelector":null,"Disabled":false},{"AnswerId":460936,"QuestionId":0,"AnswerTypeId":null,"RegularExpressionId":null,"AnswerText":"Did not reach the patient (Near Miss)","DisplayOrder":2,"Selected":null,"DefaultText":null,"Mandatory":null,"ValidatorId":null,"SyncRefMandatory":null,"FieldLength":null,"AnswerFormId":null,"EntryMaskId":null,"ShowTimeSelector":null,"Disabled":false},{"AnswerId":460937,"QuestionId":0,"AnswerTypeId":null,"RegularExpressionId":null,"AnswerText":"Unsafe Condition","DisplayOrder":3,"Selected":null,"DefaultText":null,"Mandatory":null,"ValidatorId":null,"SyncRefMandatory":null,"FieldLength":null,"AnswerFormId":null,"EntryMaskId":null,"ShowTimeSelector":null,"Disabled":false}]},{"FormId":0,"QuestionId":46080,"QuestionSelectionMode":"RadioButtonSelection","QuestionText":"<div><span style=\"font-size: larger\"><strong>Was the patient harmed?</strong></span></div>","DisplayOrder":3,"PageNumber":1,"Answers":[{"AnswerId":632595,"QuestionId":0,"AnswerTypeId":null,"RegularExpressionId":null,"AnswerText":"Yes","DisplayOrder":1,"Selected":null,"DefaultText":null,"Mandatory":null,"ValidatorId":null,"SyncRefMandatory":null,"FieldLength":null,"AnswerFormId":null,"EntryMaskId":null,"ShowTimeSelector":null,"Disabled":false},{"AnswerId":632596,"QuestionId":0,"AnswerTypeId":null,"RegularExpressionId":null,"AnswerText":"No","DisplayOrder":2,"Selected":null,"DefaultText":null,"Mandatory":null,"ValidatorId":null,"SyncRefMandatory":null,"FieldLength":null,"AnswerFormId":null,"EntryMaskId":null,"ShowTimeSelector":null,"Disabled":false}]}, and so on...

何か案は?

4

1 に答える 1

1

ifバインディングでは、ビューモデルのプロパティを参照するだけでなく、ステートメント全体を入力します。このため、単に参照するのではなく、(関数として)observableを呼び出す必要があります。翻訳:代わりに

<div data-bind="if: QuestionSelectionMode == 'CheckBoxSelection'">

あなたが持っている必要があります

<div data-bind="if: QuestionSelectionMode() == 'CheckBoxSelection'">

更新されたマークアップは次のとおりです。

<div data-bind="foreach: $data">
    <p data-bind="html: QuestionText">

    <!-- RadioButtonSelection-->
    <div data-bind="if: QuestionSelectionMode() == 'RadioButtonSelection'">
        <span data-bind="foreach: Answers">
            <input type="radio" data-bind="attr: {name: $parent.QuestionId}, value: AnswerId" /><span data-bind="text: AnswerText"></span>
        </span>
    </div>

    <!-- CheckBoxSelection-->
    <div data-bind="if: QuestionSelectionMode() == 'CheckBoxSelection'">
     <span data-bind="foreach: Answers">
            <div><input type="checkbox" data-bind="value: AnswerId"/><span data-bind="text: AnswerText"></span></div>
        </span>
    </div>

    <!-- DropDownListSelection-->
    <div data-bind="if: QuestionSelectionMode() == 'DropDownListSelection'">
        <select data-bind="options: Answers, optionsText: 'AnswerText', optionsValue: 'AnswerId'"></select>
    </div>

</div>​

そしてここに実用的なフィドルがあります:http://jsfiddle.net/g5g36/

他のいくつかの注意:

  1. pタグで「html:answers」バインディングを実行しようとしています。htmlバインディングは、既存のタグ内に配置するビューモデルにHTML文字列があることをノックアウトに通知するように設計されています。ただし、pタグ内で他のすべての種類のマークアップを定義します。このタグを完全に削除してください。

  2. JSONパーサーを満足させるには、JSONを修正して、単一のスラッシュではなく二重のスラッシュを使用する必要がありました(フィドルを参照)。サービスが処理する方法によっては、これは適切でない場合があります。

  3. $ dataはバインディングに暗黙的に含まれているため、「$ data.Answers」にバインドする代わりに、「Answers」にバインドすることができます。どちらの方法でも機能しますが、$dataを削除するとクリーンになります。

  4. 技術的には、pタグ内にdivタグを含めることは想定されていません。

  5. pタグは閉じているはずです

于 2012-12-18T04:21:12.297 に答える