动态构建单选按钮视图,使用ko.observable检查绑定不起作用(Build radio button view dynamically, checked binding is not worki

编程入门 行业动态 更新时间:2024-10-22 11:03:21
动态构建单选按钮视图,使用ko.observable检查绑定不起作用(Build radio button view dynamically, checked binding is not working using ko.observable)

这是我的第一个问题,请原谅发布问题时的任何错误。

我的问题看起来可能与Build knockout模型完全相似, 并且动态查看,未设置单选按钮

根据我的研究,上面的问题非常接近我的问题,但仍无法得到解决。

在我的要求中,对于每个问题,有多个单选按钮作为选项,还有prev和下一个导航按钮。 问题和选择是动态构建的,用户在问题上做出的选择未在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'); } }

尝试了多种选择,但无法解决我的代码有什么问题。 任何帮助是极大的赞赏。

This is my first question, pardon for any mistakes in posting the question.

My question might looks exactly similar to Build knockout model and view dynamically, radio buttons not being set

From my research, the above question comes very close to my problem, but still could not get a fix.

In my requirement, for each question there are multiple radio buttons as choices and also there are prev and next navigation buttons. The question and choices are dynamically built, the choice the user has made on the question is not being captured in the viewmodel property self.current_question.response.

Below is snippet of my view

<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 -->

Below is my snippet of my 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'); } }

Have tried multiple options, but could not get what's wrong with my code. Any help is greatly appreciated.

最满意答案

您的div#inputdiv应该看起来像这样,它将适当地处理显示单选按钮,这样您就不必使用jQuery注入DOM元素。 我的逻辑可能并不完全符合您的要求,但您可以根据需要进行调整。

with binding仅在填充其变量时才呈现其内容。 div中的变量将引用变量的成员。 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>

你的jqm绑定处理程序可能就像这样简单:

ko.bindingHandlers.jqm = { init: function (el) { $(el).create(); } };

这至少值得一试。 另外看看这篇文章 ,也许谷歌周围的jqm和淘汰赛。

Your div#inputdiv should look something like this, which will handle displaying radio buttons appropriately so that you don't have to resort to injecting DOM elements with jQuery. My logic might not be exactly what you're looking for, but you can adjust as appropriate.

The with binding will only render its contents if its variable is populated. Variables in the div will refer to the variable's members. The jqm binding is a custom binding handler you would need to write (or find).

<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>

Your jqm binding handler might be as simple as this:

ko.bindingHandlers.jqm = { init: function (el) { $(el).create(); } };

That's at least worth a shot. Also take a look at this article, and maybe google around for jqm and knockout.

更多推荐

本文发布于:2023-07-14 20:39:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1107272.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:视图   绑定   单选   按钮   不起作用

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!