简体   繁体   English

在Knockout中使用ckeditor作为observableArray的一部分

[英]Using ckeditor in Knockout as part of an observableArray

I am trying to add the Rich Text Editor to my Survey system using CKeditor and knockout. 我正在尝试使用CKeditor和剔除将RTF编辑器添加到我的测量系统中。 I have my ViewModel, which has an observerable array of quesitons. 我有ViewModel,它有一个可观察的问题数组。 I want to make the Name in each question use the ckeditor. 我想使每个问题中的名称都使用ckeditor。 I have look at the post Knockout.js: array parameter in custom binding . 我看过自定义绑定中的Knockout.js:array参数 And have immplemented that but my OnBlur is not working. 并且实现了,但是我的OnBlur无法正常工作。 The ValueAccessor() is not returning an observable object. ValueAccessor()不返回可观察对象。 So I get an error that string is not a function() on this line of code.. 所以我得到一个错误,即在该行代码中字符串不是function()。

  var observable = valueAccessor();
  observable($(element).val());

Here is my Html, I am just using a static Id for now on question, and was going to change that after I got this to work for just one question in the array. 这是我的HTML,我现在使用的是静态ID,在将其用于数组中的一个问题后,将对其进行更改。

<tbody data-bind="foreach: questionModel">
                                    <tr>
                                        <td>
                                            <button data-bind='click: $root.addQuestion' class="btn btn-success" title="Add Question"><i class="icon-plus-sign fontColorWhite"></i></button>
                                            <button data-bind='click: $root.removeQuestion' class="btn btn-danger" title="Remove Question"><i class="icon-minus-sign fontColorWhite"></i></button>
                                        </td>
                                        <td><textarea id="question123" class="RichText" data-bind="richText: Name"></textarea></td>
                                        <td><input type="checkbox" data-bind="checked: AllowComment"  /></td>
                                        <td><button data-bind="click: $root.addAnswer" class="btn btn-success" title="Add Answer"><i class="icon-plus-sign fontColorWhite"></i></button></td>
                                        <td>
                                            <div  data-bind="foreach: possibleAnswerModel">
                                                <input style="width: 278px"  style="margin-bottom: 5px;" data-bind='value: Name' />
                                                 <button data-bind='click: $root.removeAnswer' class="btn btn-danger" title="Remove Answer"><i class="icon-minus-sign fontColorWhite"></i></button>
                                            </div>
                                        </td>
                                    </tr>
                                    <tr>
                                </tbody>

Below is my ViewModel as well as my custom binding.... 下面是我的ViewModel以及我的自定义绑定。

ko.bindingHandlers.richText = {
        init: function (element, valueAccessor, allBindingsAccessor, ViewModel) {

            var txtBoxID = $(element).attr("id");

            console.log("TextBoxId: " + txtBoxID);

            var options = allBindingsAccessor().richTextOptions || {};

            options.toolbar_Full = [
                ['Bold', 'Italic'],
                ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent'],
                ['Link', 'Unlink']
            ];
            //handle disposal (if KO removes by the template binding)

            ko.utils.domNodeDisposal.addDisposeCallback(element, function() {

                if (CKEDITOR.instances[txtBoxID]) {
                    CKEDITOR.remove(CKEDITOR.instances[txtBoxID]);
                };
            });

            $(element).ckeditor(options);

            //wire up the blur event to ensure our observable is properly updated

            CKEDITOR.instances[txtBoxID].focusManager.blur = function () {
                console.log("blur");
                console.log("Value: " + valueAccessor());
                console.log("Value: " + $(element).val());

                var observable = valueAccessor();
                observable($(element).val());

           };
        },

        update: function (element, valueAccessor, allBindingsAccessor, ViewModel) {
            var value = valueAccessor();

            console.log("Value Accessor: " + value);

            var valueUnwrapped = ko.utils.unwrapObservable(value);

            //var val = ko.utils.unwrapObservable(valueAccessor());
            console.log("Value: " + valueUnwrapped);
            $(element).val(valueUnwrapped);
        }
    };

function ViewModel(survey) {
        // Data
        var self = this;

        self.StartDate = ko.observable(survey.StartDate).extend({ required: { message: 'Start Date is required' } });
        self.EndDate = ko.observable(survey.EndDate).extend({ required: { message: 'End Date is required' } });
        self.Name = ko.observable(survey.Name).extend({ required: { message: 'Name is required' } });
        self.ButtonLock = ko.observable(true);

        self.questionModel = ko.observableArray(ko.utils.arrayMap(survey.questionModel, function(question) {
            return { Id: question.QuestionId, Name: ko.observable(question.Name), Sort: question.Sort, IsActive: question.IsActive, AllowComment: question.AllowComment, possibleAnswerModel: ko.observableArray(question.possibleAnswerModel) };
        }));

        // Operations
        self.addQuestion = function () {
            self.questionModel.push({
                Id: "0",
                Name: "",
                AllowComment: true,
                Sort: self.questionModel().length + 1,
                possibleAnswerModel: ko.observableArray(),
                IsActive:true
            });
        };

        self.addAnswer = function (question) {
            question.possibleAnswerModel.push({
                Id: "0",
                Name: "",
                Sort: question.possibleAnswerModel().length + 1,
                IsActive:true
            });
        };

        self.GetBallotById = function (id) {
            for (var c = 0; c < self.BallotProjectStandardList().length; c++) {
                if (self.BallotProjectStandardList()[c].BallotId === id) {
                    return self.BallotProjectStandardList()[c];
                }
            }
            return null;
        };

        self.removeQuestion = function(question) { self.questionModel.remove(question); };

        self.removeAnswer = function(possibleAnswer) { $.each(self.questionModel(), function() { this.possibleAnswerModel.remove(possibleAnswer) }) };

        self.save = function() {
            if (self.errors().length == 0) {
                self.ButtonLock(true);
                $.ajax("@Url.Content("~/Survey/Create/")", {
                    data: ko.toJSON(self),
                    type: "post",
                    contentType: 'application/json',
                    dataType: 'json',
                    success: function(data) { self.successHandler(data, data.success); },
                    error: function() {
                        self.ButtonLock(true);
                        self.errorHandler();
                    }
                });
            } else {
                self.errors.showAllMessages();
            }
        };
    }

    ViewModel.prototype = new ErrorHandlingViewModel();
    var mainViewModel = new ViewModel(@Html.Raw(jsonData));
    mainViewModel.errors = ko.validation.group(mainViewModel);
    ko.applyBindings(mainViewModel);

I figured what I was doing wrong. 我发现自己做错了。 When I define the observableArray() I was defining the object as ko.observable, however, when I add a question to the array, I was initializing it as a string. 当我定义observableArray()时,我将对象定义为ko.observable,但是,当我向数组中添加问题时,我将其初始化为字符串。 So I change that to match and it worked like a champ. 因此,我将其更改为与之匹配,并且像冠军一样工作。 Here is the change push. 这是变革的推动力。

     self.questionModel = ko.observableArray(ko.utils.arrayMap(survey.questionModel, function(question) {
            return { Id: question.QuestionId, Name: ko.observable(question.Name), Sort: question.Sort, IsActive: question.IsActive, AllowComment: question.AllowComment, possibleAnswerModel: ko.observableArray(question.possibleAnswerModel) };
        }));

        // Operations
        self.addQuestion = function () {
            self.questionModel.push({
                Id: "0",
                Name: ko.observable(),
                AllowComment: true,
                Sort: self.questionModel().length + 1,
                possibleAnswerModel: ko.observableArray(),
                IsActive:true
            });
        }; 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM