【问题标题】:Dojo domConstruct.create won't create element on postCreateDojo domConstruct.create 不会在 postCreate 上创建元素
【发布时间】:2015-08-18 09:51:03
【问题描述】:

我是 Dojo 的新手,我正在制作我的第一个小部件以在 EPiServer CMS 中使用。 该小部件应该在单击按钮时动态添加联系人。这意味着我的 templateString 唯一的控件是一个按钮。单击它时,我调用一个函数,该函数创建将包含联系信息的所有其他控件,例如姓名、电子邮件等。这工作正常,我使用 domConstruct.create 没有问题。

问题是,当我想根据来自服务器的值创建现有联系人时,我无法使用 domConstruct.create,它只会返回“未定义”。我在 DOM 准备好后发生的 postCreate 事件中进行调用。 (我也对此进行了测试)。有谁知道可能出了什么问题?就像我说的那样,在单击“添加”按钮时创建控件就像一种魅力。

抛出错误的函数是:

postCreate: function () {
            // call base implementation
            this.inherited(arguments);

            //this._loadContacts(this.value);
            var node = domConstruct.create("fieldset", { id: "test" }, "cccp"); //this simple create instruction returns undefined here. 

            //Bind button
            this.connect(this.btnAdd, "onclick", dojo.partial(this._createContact, new Object()));

        },

正好在执行 domConstruct.create 的那一行。以下是小部件的完整代码:

define([
    "dojo/_base/array",
    "dojo/_base/connect",
    "dojo/_base/declare",
    "dojo/_base/lang",
    "dojo/dom-construct",
    "dojo/on",


    "dijit/_CssStateMixin",
    "dijit/_Widget",
    "dijit/_TemplatedMixin",
    "dijit/_WidgetsInTemplateMixin",

    "epi/epi",
    "epi/shell/widget/_ValueRequiredMixin"
],
function (
    array,
    connect,
    declare,
    lang,
    domConstruct,
    on,

    _CssStateMixin,
    _Widget,
    _TemplatedMixin,
    _WidgetsInTemplateMixin,

    epi,
    _ValueRequiredMixin
) {
    var amountContacts = 0;
    var contactContainerPrefixName = "contactInfo";

    return declare("meridian.editors.StringList", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin, _CssStateMixin, _ValueRequiredMixin], {

        templateString: "<div class=\"dijitInline\">\
                            <form id=\"cccp\" action=\"\">\
                            </form>\
                            <button id=\"btnAdd\" data-dojo-attach-point=\"btnAdd\" type=\"button\" class=\"\">Add Contact</button><br/> \
                            <span>${helptext}</span>\
                        </div>",

        baseClass: "epiStringList",

        helptext: "Place items on separate lines",

        intermediateChanges: false,

        value: null,

        multiple: true,

        onChange: function (value) { },

        _onChange: function (value) {
            this.onChange(value);
        },

        postCreate: function () {
            // call base implementation
            this.inherited(arguments);

            //this._loadContacts(this.value);
            var node = domConstruct.create("fieldset", { id: "test" }, "cccp"); //this simple create instruction returns undefined here. 

            //Bind button
            this.connect(this.btnAdd, "onclick", dojo.partial(this._createContact, new Object()));

        },

        isValid: function () {
            // summary:
            //    Check if widget's value is valid.
            // tags:
            //    protected, override

            return !this.required || lang.isArray(this.value) && this.value.length > 0 && this.value.join() != "";
        },


        _loadContacts:function(data)
        {
            for (var i = 0; i < data.length; i++) {
                this._createContact(data[i]);
            }
        },


        _createContact:function(data)
        {
            //increase the number of contacts
            amountContacts++;
            var contactInfoContainer = contactContainerPrefixName+amountContacts;

            //Create container for contact data
            var contactInfo = domConstruct.create("fieldset", { id: contactInfoContainer }, "cccp");

            //Create container for PROPERTIES
            var contactInfoProperties = domConstruct.create("div",  {class: "properties"}, contactInfoContainer);

            //Name
            this._createTextbox("name", data.fullName, "Name", contactInfoProperties, false, false);

            /*//Email
            this._createTextbox("email", "Email", contactInfoProperties, false);

            //Phone 1
            this._createTextbox("phoneOne", "Phone 1", contactInfoProperties, true);

            //Phone 2
            this._createTextbox("phoneTwo", "Phone 2", contactInfoProperties, true);

            //Fax
            this._createTextbox("fax", "Fax", contactInfoProperties, false);

            //Organization
            this._createTextbox("organization", "Organization", contactInfoProperties, false);

            //Department
            this._createTextbox("department", "Department/Unit", contactInfoProperties, false);

            //Role
            this._createTextbox("role", "Role/Job title", contactInfoProperties, false);*/

            //Website
            this._createTextbox("website", data.website, "Website", contactInfoProperties, false, false);

            //Address
            //this._createTextbox("address", "Address", contactInfoProperties, false);

            //TLP
            this._createTLP_DDL("tlp", "TLP", contactInfoProperties);


            //Create container for CATEGORIES
            var contactInfoCategories = domConstruct.create("div", { class: "categories" }, contactInfoContainer);

            //Categories heading
            var p=domConstruct.create("p", { class: "heading" }, contactInfoCategories);
            p.innerHTML = "Categories";

            //Alert, Warning & Incident Response
            this._createCategory("alert", contactInfoCategories, "Alert, Warning & Incident Response");

            //Threat
            this._createCategory("threat", contactInfoCategories, "Threat");

            //Vulnerability
            this._createCategory("vulnerability", contactInfoCategories, "Vulnerability");

            //Industry
            this._createCategory("industry", contactInfoCategories, "Industry");

            //Policy
            this._createCategory("policy", contactInfoCategories, "Policy");

            //R & D
            this._createCategory("rd", contactInfoCategories, "R & D");

            //Sharing
            this._createCategory("sharing", contactInfoCategories, "Sharing");

            //Crime
            this._createCategory("crime", contactInfoCategories, "Crime");

            //SCADA/Process Control
            this._createCategory("scada", contactInfoCategories, "SCADA/Process Control");

            //Assurance
            this._createCategory("assurance", contactInfoCategories, "Assurance");

            //Standards
            this._createCategory("standards", contactInfoCategories, "Standards");

            //Resilience
            this._createCategory("resilience", contactInfoCategories, "Resilience");

            //Exercises
            this._createCategory("exercises", contactInfoCategories, "Exercises");

            //Defence
            this._createCategory("defence", contactInfoCategories, "Defence");

            //Media handling
            this._createCategory("media", contactInfoCategories, "Media handling");

            //General PoC
            this._createCategory("poc", contactInfoCategories, "General PoC");



            //Add remove button
            var btnRemove = domConstruct.create("input", { type: "button", id: "btnRemove" + amountContacts, value: "Remove"/*,onclick:"_deleteContact(this)"*/ }, contactInfo);
            this.connect(btnRemove, "onclick", dojo.partial(this._deleteContact, btnRemove.id));

        },

        _createTextbox:function(id, textBoxValue, labelText, parent, checkbox, checkboxChecked)
        {
            var currentId = id+amountContacts;

            var textboxContainer = domConstruct.create("div",  {class:"form-item"}, parent);

            this._createLabel(currentId, textboxContainer, labelText);

            //Create textbox and attach update handler
            var textbox = domConstruct.create("input", { type: "text", id: currentId, name: currentId }, textboxContainer);
            if (textBoxValue)
                textbox.value = textBoxValue;

            this.connect(textbox, "onchange", this._updateValue);

            if (checkbox) {
                this._createCheckbox("inline", textboxContainer, currentId + "_24", "24/7?");
            }
        },


        _createTLP_DDL:function(id, labelText, parent)
        {
            var currentId = id+amountContacts;

            var ddlContainer = domConstruct.create("div", { class: "form-item" }, parent);
            this._createLabel(currentId, ddlContainer, labelText);

            var ddl = domConstruct.create("select", { name: currentId, id: currentId }, ddlContainer);

            //Add options
            var option1 = domConstruct.create("option", { val: "-1" }, ddl);
            option1.innerHTML = "None";

            var option1 = domConstruct.create("option", { val: "1" }, ddl);
            option1.innerHTML = "Yes";

            var option1 = domConstruct.create("option", { val: "0" }, ddl);
            option1.innerHTML = "No";
        },

        _createCategory:function(id, parent, checkboxText)
        {
            var currentId = id + amountContacts;


            var categoryContainer = domConstruct.create("div", { class: "form-item inline" }, parent);
            this._createCheckbox("", categoryContainer, currentId, checkboxText);
        },

        _createLabel:function(forId, container, labelText)
        {
            var label = domConstruct.create("label", { for: forId }, container);
            label.innerHTML = labelText;
        },

        _createCheckbox:function(labelClass, container, checkboxId, checkboxText){
            var labelCheckbox = domConstruct.create("label", { class: labelClass }, container);

            //Create checkbox and attach update handler
            var checkbox = domConstruct.create("input", { type: "checkbox", id: checkboxId, name: checkboxId }, labelCheckbox);
            this.connect(checkbox, "onchange", this._updateValue);

            var span = domConstruct.create("span", {}, labelCheckbox);
            span.innerHTML = checkboxText;
        },

        _deleteContact:function(targetBtnId)
        {
            var userInput = window.confirm("Are you sure you want to delete this contact?");
            if (userInput) {
                dojo.destroy(contactContainerPrefixName+targetBtnId[targetBtnId.length-1]);
            }
        },

        _updateValue: function () {
            //TODO: Delete test data
            var contacts = [];

            //The amount of contacts can have changed after deletions, so the global variables might not hold the real value
            var actualAmountContacts = 0;

            for (var i = 1; i <= amountContacts; i++) {
                if (this._isValidContact(i)) {

                    var currentContact = new Object();
                    currentContact.fullName = this._getValueById("name" + i);
                    currentContact.website = this._getValueById("website" + i);

                    contacts[actualAmountContacts] = currentContact;
                    actualAmountContacts++;
                }
            }



            this._set("value", contacts);
            this.onChange(contacts);
        },

        _getValueById: function (id) {
            var node = dojo.byId(id);
            var textValue = (node != null) ? node.value : "";
            return textValue;

        },

        _isValidContact:function(itemNumber){
            //If there's no name or telephone then it's not a valid contact
            return (this._getValueById("name" + itemNumber) != "" || this._getValueById("phoneOne" + itemNumber) != "" || this._getValueById("phoneTwo" + itemNumber) != "");
        },
    });
});

更新: 经过大量测试后,我意识到导致错误的不是 domConstruct.create 语句,问题是具有“id:cccp”并且我要附加创建的元素的表单元素此时为空.正如您在源代码中看到的那样,它在 templateString 中定义,但在 postCreate 方法中仍然为空。所以现在的问题是,加载 templateString 中的 HTML 时会触发什么事件?

【问题讨论】:

  • 代码太多,无法阅读。你能给我们你得到错误的sn-p吗?当您发出服务器请求时,您很可能使用异步调用。要处理异步调用,您需要使用承诺或传递回调函数来处理数据。您不能使用正常的赋值函数调用来获取数据。
  • 我已编辑问题并添加了导致错误的 sn-p。有时您需要更多代码才能真正看到上下文。无论如何,我不是手动做任何服务器请求,而是 CMS 为我做的。在调用“postCreate”方法时,对象“this.value”已经拥有保存在服务器上的正确数据。为简单起见,现在对使用此数据的行进行了注释。当我使用硬编码数据创建随机元素时,错误仍然存​​在。

标签: dojo widget episerver


【解决方案1】:

最后我解决了这个问题,所以我在这里写了解决方法,我希望它可以帮助别人! 我更改了 templateString 并将属性 data-dojo-attach-point=\"form\" 添加到未找到的表单中。然后在 postCreate 方法中,我使用这个 (this.form ) 访问了表单,它可以正常工作。该函数的最终实现结果如下:

postCreate: function () {
            // call base implementation
            this.inherited(arguments);

            //this._loadContacts(this.value);
            var node = domConstruct.create("fieldset", { id: "test" }, this.form); //this simple create instruction returns undefined here. 

            //Bind button
            this.connect(this.btnAdd, "onclick", dojo.partial(this._createContact, new Object()));

        },

我仍然不明白为什么dojo.byId("cccp") 会返回 null,但我很高兴我找到了解决问题的解决方法。干杯!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多