<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将查询数据库,获取该字段的配置并将其转换为dropbox
,checkbox
或者说, date picker
labels
,validation
以及其他所有的花里胡哨。
答案 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>