Knockout自定义绑定可动态增强JQM内容

时间:2015-12-14 15:08:46

标签: jquery jquery-mobile knockout.js radio-button

我已经重新组织了我的问题。

首先我有一个问题页面,页面包含

  1. 问题文本
  2. 选择
  3. 下一步,上传和提交按钮(如适用)
  4. 页面的代码段位于

    之下
     <div id="questionpage" data-role="page" data-theme="c">
    
        <div data-role="header">
          <h1>Question <span data-bind="text: current_question().queNo"></span></h1>
        </div><!-- /header -->
    
        <!-- inputs -->
        <div id="inputs" data-role="content" >    
          <a id="prevbtn" href="#question" data-bind="click: $root.prev, visible: hasPrev()" data-role="button" >Prev</a>
          <a id="nextbtn" href="#question" data-bind="click: $root.next, visible: hasNext()" data-role="button">Next</a>     
          <a id="completebtn" href="#question" data-bind="click: $root.submit, visible: !hasNext()" data-role="button">Submit</a>
    
          <p data-bind="text: current_question().queText"></p>
          <div id="inputdiv" data-bind="with:$root.current_question, enhancedom: $root.current_question">
            <div id="radio">
                <fieldset id="radiocontrol" data-role="controlgroup" data-bind="foreach:options">
                    <input name="radio-options" type="radio" data-bind="value: $data, checked: $root.current_question().response, attr: {id:'rb_' + $index() }" />
                    <label data-bind="attr:{for: 'rb_' + $index() }, text: $data"></label>
                </fieldset>
            </div>
          </div>
    
        </div><!-- /content -->    
    </div><!-- /page -->
    

    问题及其选择是从服务器获取的,它们绑定到Viewmodel属性。 以下是页面的支持javascript和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.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);
    
            $.mobile.loading('hide');
        }
    
        // function executed when the user clicks the 'prev' button
        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);
            $.mobile.loading('hide');
        }
    
        // An AJAX call is made and this is 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);
                }
    
            }
            else if (event.type === 'exception')
            {
                self.error(event.message);
            }
        }
    
    }
        // enhancedom custom binding
        // runs jQuery Mobile on updated DOM elements
        ko.bindingHandlers.enhancedom = {
            update: function (element) {
                $(element).trigger("create");
            }
        };
    
        // bind event onto the display of the 'loading' page - the first stacked div (logical page)
        // this creates the viewmodel which handles the loading etc
        $( "#loadingpage" ).on( "pageshow", function() {
            if (null==viewModel)
            {         
    
                viewModel=new ExamViewModel();
    
                ko.applyBindings(viewModel);
            }
        });
    

    鉴于这个场景,我的问题有2个部分

    1. enhancedom上没有任何自定义绑定<div id="inputdiv"></div> 代码工作得很好,用户选择的选项是 保留在导航中,他可以提交,但广播 按钮选项不是JQM增强
    2. 为了让JQM增强单选按钮(问题是什么时候) 我编写了这个自定义绑定enhancedom。在这种情况下 JQM增强功能正在运行,但我正在丢失用户的响应 在导航上选择。
    3. 我认为我在整合KO和JQM方面缺少一些东西,我根据我的研究尝试了一些选项,但无法弄清楚问题。非常感谢任何帮助。

0 个答案:

没有答案