Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/449.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 动态生成单选按钮视图,使用ko.observable检查绑定不起作用_Javascript_Jquery Mobile_Knockout.js_Radio Button - Fatal编程技术网

Javascript 动态生成单选按钮视图,使用ko.observable检查绑定不起作用

Javascript 动态生成单选按钮视图,使用ko.observable检查绑定不起作用,javascript,jquery-mobile,knockout.js,radio-button,Javascript,Jquery Mobile,Knockout.js,Radio Button,这是我的第一个问题,请原谅我在发帖时的错误 我的问题可能看起来与 根据我的研究,上述问题与我的问题非常接近,但仍然无法解决 在我的要求中,每个问题都有多个单选按钮可供选择,还有上一个和下一个导航按钮。 问题和选项是动态生成的,用户对问题所做的选择不会在viewmodel属性self.current_question.response中捕获 下面是我的观点的片段 <div id="questionpage" data-role="page" data-theme="c">

这是我的第一个问题,请原谅我在发帖时的错误

我的问题可能看起来与

根据我的研究,上述问题与我的问题非常接近,但仍然无法解决

在我的要求中,每个问题都有多个单选按钮可供选择,还有上一个和下一个导航按钮。 问题和选项是动态生成的,用户对问题所做的选择不会在viewmodel属性self.current_question.response中捕获

下面是我的观点的片段

<div id="questionpage" data-role="page" data-theme="c">

    <div data-role="header" data-theme="c">
      <h1>Question <span data-bind="text: current_question().queNo"></span></h1>
    </div><!-- /header -->

    <!-- inputs -->
    <div id="inputs" data-role="content" data-theme="c">    
      <a id="prevbtn" href="#question" data-icon="arrow-l" data-bind="click: $root.prev, visible: hasPrev()" data-role="button" data-inline="true">Prev</a>
      <a id="nextbtn" href="#question" data-icon="arrow-r" data-bind="click: $root.next, visible: hasNext()" data-role="button" data-inline="true">Next</a>     
      <a id="completebtn" href="#question" data-icon="check" data-bind="click: $root.submit, visible: !hasNext()" data-role="button" data-inline="true">Submit</a>

      <p data-bind="text: current_question().queText"></p>
      <div id="inputdiv">
      </div>

    </div><!-- /content -->    
</div><!-- /page -->

问题:

下面是我的Viewmodel的片段

// Question response object

    function QuestionResponse(stuId, examQueId,selAns)
    {
        var self=this;
        self.Student__c=stuId;
        self.Exam_Question__c=examQueId;
        self.Selected_Answer__c=selAns;
    }

    // Question object
    function Question()
    { 
        var self=this;
        self.response=ko.observable('');
        self.options=ko.observableArray();
    }

    function Question(id, queNo, queText, response, queChA, queChB, queChC, queChD, queChE)
    {
        var self=this;
        self.id=id;
        self.queNo=queNo;
        self.queText=queText;
        self.response=ko.observable(response);
        self.options=ko.observableArray();
        //self.checked=ko.observableArray();

        // helper function to add an option
        self.addOption = function(option)
        {
            if (null!=option)
            {
                self.options().push(option);
            }
        }

        self.addOption(queChA);
        self.addOption(queChB);
        self.addOption(queChC);
        self.addOption(queChD);
        self.addOption(queChE);
    }

    function ExamViewModel()
    {
        var self=this;

        // initialise variables to default observables
        // self.question_response=ko.observable(new QuestionResponse());
        self.current_question=ko.observable(new Question());
        self.current_question_no=0;
        self.email=ko.observable('Your email id');
        self.questions=ko.observableArray();
        self.studentId;

        self.errorMsg=ko.observable('');
        self.completeMsg=ko.observable('');
        self.hasPrevious=ko.observable();
        self.hasNext=ko.observable(false);
        self.hasPrev=ko.observable(false);

        // function executed when the user clicks the 'next' button
        self.next=function()
        {
            $.mobile.loading( 'show', { theme: "a", text: "Loading", textVisible: true });

            // advance to the next question
            self.current_question_no++;
            self.current_question(self.questions()[self.current_question_no]());

            // setup previous/next buttons
            self.hasPrev(true);
            self.hasNext(self.current_question_no<self.questions().length-1);

            // add the input markup
            self.addInput();
            $.mobile.loading('hide');
        }

        // function executed when the user clicks the 'prev' button - could refactor
        // some of this and the next function into a common helper
        self.prev=function()
        {
            $.mobile.loading( 'show', { theme: "a", text: "Loading", textVisible: true });
            //alert('in prev '+self.current_question().response);
            self.current_question_no--;
            self.current_question(self.questions()[self.current_question_no]());
            self.hasPrev(self.current_question_no!=0);
            self.hasNext(true);
            self.addInput();
            $.mobile.loading('hide');
        }

        // callback for the JavaScript remoting call    
        self.responseCB=function(record, event)
        {
            if ( (!event) || (event.status) ) 
            {
                $.each(record,
                        function()
                        {
                            var question=new ko.observable(new Question(
                                                            this.Id, this.Exam_Question_Number__c, this.Question__r.Question_Text__c,'', 
                                                            this.Question__r.ChoiceA__c, this.Question__r.ChoiceB__c, this.Question__r.ChoiceC__c,
                                                            this.Question__r.ChoiceD__c,this.Question__r.ChoiceE__c));

                            self.questions.push(question);

                            // if the current question is empty, set it to this question 
                            if (typeof self.current_question().queText === 'undefined')
                            {
                                self.current_question(question());
                            }
                        });

                // setup whether to display the next button                             
                if (self.questions().length>1)
                {
                    self.hasNext(true);
                }

                // add the input markup
                self.addInput();
            }
            else if (event.type === 'exception')
            {
                self.error(event.message);
            }
        }

        // add the appropriate input markup
        self.addInput=function()
        {
            self.addRadioInput();

        }


        self.addRadioInput=function()
        {
            $('#inputdiv').html(
                '<div id="radio" data-bind="value: $root.current_question.response">' +
                '   <fieldset id="radiocontrol" data-role="controlgroup">' + 
                '       <' +  // Visualforce will break the comment that encloses the containerless element, so split over two lines
                '!-- ko foreach: current_question().options --> ' +
                '       <input name="radio-options" type="radio" data-bind="value: $data, checked: $root.current_question.response, attr: {id:\'rb_\' + $index() }"></input> ' +
                '       <label data-bind="attr:{for : \'rb_\' + $index() }, text: $data"></label> ' + 
                '       <' + 
                '!-- /ko --> ' +
                '   </fieldset> ' +
                '</div> ');

            // bind the new markup to the viewmodel
            ko.applyBindings(viewModel, $('#radio')[0]);

            // trigger JQM to enhance the newly created radio button div
            $('#radio').trigger('create');
        }


    }
//问题响应对象
函数问题响应(stuId、examQueId、selAns)
{
var self=这个;
self.Student\uuu c=stuId;
self.Exam\u Question\u c=examQueId;
self.Selected_uAnswer_uuC=selAns;
}
//问题对象
函数问题()
{ 
var self=这个;
自我反应=可观察(“”);
self.options=ko.observearray();
}
功能问题(id、queNo、queText、response、queChA、queChB、queChC、queChD、queChE)
{
var self=这个;
self.id=id;
self.queNo=queNo;
self.queText=queText;
自我反应=可观察(反应);
self.options=ko.observearray();
//self.checked=ko.observearray();
//用于添加选项的帮助器函数
self.addOption=函数(选项)
{
如果(null!=选项)
{
self.options().push(选项);
}
}
self.addOption(queChA);
self.addOption(queChB);
self.addOption(queChC);
self.addOption(queChD);
self.addOption(queChE);
}
函数ExamViewModel()
{
var self=这个;
//将变量初始化为默认观察值
//self.question_response=ko.observable(新的QuestionResponse());
self.current_question=ko.observable(新问题());
自身当前问题编号=0;
self.email=ko.observable(“您的电子邮件id”);
self.questions=ko.observearray();
自学成才;
self.errorMsg=ko.可观察(“”);
自我完成SG=可观察到的ko(“”);
self.hasPrevious=ko.observable();
self.hasNext=ko.可观察(假);
self.hasPrev=ko.可观察(假);
//用户单击“下一步”按钮时执行的函数
self.next=函数()
{
$.mobile.loading('show',{theme:“a”,text:“loading”,textVisible:true});
//进入下一个问题
self.current_question_no++;
self.current_-question(self.questions()[self.current_-question_-no]());
//设置上一个/下一个按钮
self.hasprov(真);
self.hasNext(self.current\u问题1)
{
self.hasNext(true);
}
//添加输入标记
self.addInput();
}
else if(event.type==='exception')
{
self.error(事件消息);
}
}
//添加适当的输入标记
self.addInput=函数()
{
self.addRadioInput();
}
self.addRadioInput=函数()
{
$('#inputdiv').html(
'' +
'   ' + 
'        ' +
'        ' +
'        ' + 
'        ' +
'    ' +
' ');
//将新标记绑定到viewmodel
ko.applyBindings(viewModel,$(#radio')[0]);
//触发JQM以增强新创建的单选按钮div
$('#radio')。触发器('create');
}
}
已经尝试了多个选项,但无法找到我的代码的错误。非常感谢您的帮助。

您的
div#inputdiv
应该是这样的,它可以适当地显示单选按钮,这样您就不必借助jQuery注入DOM元素。我的逻辑可能不完全符合您的要求,但您可以根据需要进行调整

带有绑定的
仅在填充其变量时才会呈现其内容。div中的变量将引用变量的成员。
jqm
绑定是您需要编写(或查找)的自定义绑定处理程序


那至少值得一试。还可以查看一下,或者在谷歌上搜索jqm和knockout。

问题是您在viewmodel中使用了jQuery,这意味着您没有正确地建模视图。如果没有看到您的radiobutton HTML和绑定,我们就看不出您为什么没有获得所选的值集。radiobutton HTML是在viewmodel函数self.addRadioInput中动态构建的,插入该单选按钮的HTML div标记是
。如果我遗漏了什么,请告诉我。通过jQuery插入代码是错误的做法。敲除可以处理动态创建元素。单选按钮上的绑定似乎适合设置
response
。为什么在
div#radio
上有
绑定?是的,没有必要在
div#radio
上绑定
值,但我正在尝试您建议的方法。谢谢您的回答,您刚刚解决了我的问题。对于您提出的第一个问题,您问我为什么要使用jQuery构建视图,这是因为我从研究中了解到,一旦加载页面,JQM增强将无法工作。现在,尽管人们的回答越来越多,但问题和选择却越来越多
<div id="inputdiv" data-bind="with:$root.current_question">
  <div id="radio" data-bind="jqm: true">
    <fieldset id="radiocontrol" data-role="controlgroup" data-bind="foreach:options">
      <input name="radio-options" type="radio" data-bind="value: $data, checked: response, attr: {id:'rb_' + $index() }" />
      <label data-bind="attr:{for: 'rb_' + $index() }, text: $data"></label>
    </fieldset>
  </div>
</div>
ko.bindingHandlers.jqm = {
  init: function (el) {
    $(el).create();
  }
};