用新构造的DOM结构替换widget元素

时间:2013-12-13 06:38:49

标签: javascript jquery html jquery-ui widget

<script>
(function( $ ) {

    $.widget( "my.dropbox", {
        errorText: function(text) {
            $(this.element).next().html(text);
        },

        _create: function() {
             var id = $(this.element).attr("id");
             var customDropbox = $(
                "<div class='form-group'>"+
                   "<label for='"+id+"'>"+getLabelFor(id)+"</label>"+
                   "<select id='"+id+"'></select>"+
                   "<div class='errors'></div>"+
                "</div>"
             );
             customDropbox.attr("id", id);

             $(this.element).replaceWith(customDropbox); // This removes original element from DOM

             populateOptions(id);
        },


    });

}( jQuery ));

$(document).ready(function(){
    $("#field1").dropbox(); //blank input field turns into a select with a label, populated options e.t.c..
    $("#button1").on("click", function(){
        $("#field1").dropbox("errorText", "This is a validation error message"); //throws an error saying dropbox is not initialized 
    });
});
</script>
<html>
     <body>
         <input id="field1" />
         <button id="button1">Press me</button>
     </body>
</html>

所以我想要一个带有公共方法的小部件,它将用与之关联的所有小部件数据替换原始元素。上面代码的问题是<select..>元素只是一个DOM元素,如果你在它上面调用.dropbox(..),它会说小部件没有被初始化。有没有办法使用.errorText()方法将select元素放入widget对象中?在线的所有小部件示例都会在原始元素周围添加内容,但永远不会替至于更大的图景,我试图制作一个动态配置表单的通用工具。它将成为html中的所有<input id="...">但是javascript将查询数据库,获取该字段的配置并将其转换为dropboxcheckbox或者说, date picker labelsvalidation以及其他所有的花里胡哨。

3 个答案:

答案 0 :(得分:6)

您的窗口小部件代码存在多个问题。我会试着总结一下:

<强> 1。复制数据

您没有将data复制到新创建的customDropbox,所以

之前
this.element.replaceWith(customDropbox);

您应该复制data

customDropbox.data(this.element.data());

现在,小部件将记住它已初始化。

<强> 2。 this.element消失了

this.element.replaceWith(customDropbox);

您应该更新this.element,以便它指向新创建的customDropbox

this.element = customDropbox;

第3。 errorText消息采用错误的元素

由于小部件元素(this.element)现在指向<div class='form-group'></div>元素,因此errorText函数必须稍微修改为:

this.element.find(".errors").html(text);

<强> 4。 id应该是唯一的

现在,包装器<div><select>都具有相同的ID,这在HTML中是不允许的,因此请删除<select>标记上的ID。幸运的是,<label>可以在没有for属性的情况下工作,只需按照以下方式编写:

<label>labelForId <select></select></label> 

然后要获取<select> - 元素,请在小部件中使用this.element.find("select")

旁注

`this.element` is already a jQuery element, so no need for the additional `$()` wrapping.

请参阅此jsFiddle

答案 1 :(得分:0)

function show(){
   $("#field1").input({....});
}

function hide(){
    $("#field1").input("hide");
}

<button onclick="show()">show</button>
<button onclick="hide()">hide</button>

答案 2 :(得分:-1)

我认为要替换原始元素,初始dropbox()不是一个好的解决方案,

因为这会迫使你依赖jQuery ui factory的实现细节,

很容易出错或引入错误,有时候其他人更难理解你的代码

如果jquery ui factory将来更改实现,则必须修改所有代码才能使其正常工作

(对不起我对jquery ui的限制了解)

我认为我们可以将<input/>放入容器中并在容器上放置初始dropbox()

<input/>替换为<select> datepicker .. ..我们可以轻松构建模块:

<form>
  <div class="dropbox"><label for="someID">aaaaaa</label><input id="someID"/></div>
  <div class="datepicker"></div>
  <div class="othermodule"></div>
</form>

JS:

$(".dropbox").dropbox(); // init dropbox you defined 
$(".datepicker").datepicker(); // ...
$(".othermodule").othermodule(); // ...

$(".dropbox").dropbox("errorText", "error"); // invoke it smoothly

这是一个简单的演示:http://jsfiddle.net/m4A3D/

@Wouter Huysentruit的回答为我提供了一个很好的建议清单

<form>
  <div class="dropbox">
      <label for="someID">aaaaaa</label>
      <input id="someID"/>
  </div>
  <div class="datepicker"></div>
  <div class="othermodule"></div>
</form>
<button id="button1">Press me</button>



  <script>
  (function ($){
     $.widget("my.dropbox", {
        _create: function () {
            var $input = this.element.find("input");
            var sID = $input.attr("id");
            var $select = $("<select>");
            $select.attr("id", sID);
            $input.replaceWith($select);

            this.element.append("<div class='errors'></div>");
        }, // end _create()
        errorText: function (text) {
            this.element.find(".errors").text(text);
        } // end errorText()
    }); 
  }(jQuery));


$(".dropbox").dropbox();
$("#button1").click(function () {
    $(".dropbox").dropbox("errorText", "this is error");
});
  </script>