0

我正在尝试使用 ext_scaffold 为 Rails 支持的 Web 应用程序生成 UI 元素。

但是,我遇到了布尔字段行为的问题。例如,当我这样做时

./script/generate ext_scaffold product name:string description:text sku:integer available:boolean

它会正确构建迁移并生成带有布尔字段复选框的用户界面。

但是,选中此框只会修改正在创建的对象。如果记录已存在,则复选框的状态准确地反映了该字段。但是,编辑它失败了——即,选中或取消选中它并保存记录并不会改变它。

深入代码,我们发现:

 items: [
    { fieldLabel: scaffoldPanel.labels['product[name]'], name: 'product[name]', xtype: 'textfield' },
    // ... other fields ...
    { fieldLabel: scaffoldPanel.labels['product[available]'], name: 'product[available]', xtype: 'checkbox', inputValue: '1' }, { xtype: 'hidden', name: 'product[available]', value: '0' }
    ],

我觉得问题在于 Rails 或 Ext 对同名元素感到困惑。无论哪种方式,在创建记录后,单击复选框不会执行任何操作(选中或未选中,该字段保持为“0”。)

在玩了一会儿之后,事实证明,如果我们将隐藏字段放在复选框上方,则无论该字段现在在编辑后设置为 true 。也不完全是理想的行为。

有没有其他人遇到过这个问题?有什么解决方法吗?谢谢。

更新:

请注意,即使选中了该字段的复选框,发送的 POST 请求也表明该字段设置为 false。所有其他字段类型正在适当更新...

更新2:

好吧,找到了一篇很棒的博客文章,描述了 Semergence 对这个问题的解决方案,但我仍然无法让它发挥作用......我已将他的解决方案改编如下:

   onOk: function() { 

      // ....

      if (scaffoldPanel.getFormPanel().currentMode == 'edit') {
        // set up request for Rails create action
        submitOptions.params._method = 'PUT';
        submitOptions.url = submitOptions.url + '/' + selected.data.id;
      }

  // ----- checkbox serializer ------
     var serializedForm = scaffoldPanel.getFormPanel().getForm();

 // because unchecked checkboxes do not submit values, manually force a value of 0  
     serializedForm.items.each(function(f) {  
        //alert("Checking \"" + f.getName() "\" field...");
        if (f.isFormField && f.getXType() == 'checkbox' && !f.getValue()) {  
            alert("Auto setting \"" + f.getName() + "\" field to 0...");
            serializedForm.getValues()[f.getName()] = '0';  
        }
      });
// ------- end serializer -------

     serializedForm.submit(submitOptions);
     //scaffoldPanel.getFormPanel().getForm().submit(submitOptions);  
   },

现在警报被正确抛出,指示正确的字段并断言它将被设置为零。

除非这不会发生在实际发送的 post 请求中——事实上,如果未选中该复选框,则它在 POST 中根本没有值。

有人可以帮我理解这里发生了什么吗?

4

1 回答 1

1

好的,事实证明这是 Ext 框架的一个已知错误。如果您遇到同样的问题,请访问 Extjs 论坛,那里列出了几种解决方案。最简单的实现就是扩展复选框类:

# patch.js -- include before creating any checkboxes
Ext.ns('Ext.ux.form');
Ext.ux.form.XCheckbox = Ext.extend(Ext.form.Checkbox, {
 offCls:'xcheckbox-off'
,onCls:'xcheckbox-on'
,disabledClass:'xcheckbox-disabled'
,submitOffValue:'false'
,submitOnValue:'true'
,checked:false

,onRender:function(ct) {
    // call parent
    Ext.ux.form.XCheckbox.superclass.onRender.apply(this, arguments);

    // save tabIndex remove & re-create this.el
    var tabIndex = this.el.dom.tabIndex;
    var id = this.el.dom.id;
    this.el.remove();
    this.el = ct.createChild({tag:'input', type:'hidden', name:this.name, id:id});

    // update value of hidden field
    this.updateHidden();

    // adjust wrap class and create link with bg image to click on
    this.wrap.replaceClass('x-form-check-wrap', 'xcheckbox-wrap');
    this.cbEl = this.wrap.createChild({tag:'a', href:'#', cls:this.checked ? this.onCls : this.offCls});

    // reposition boxLabel if any
    var boxLabel = this.wrap.down('label');
    if(boxLabel) {
        this.wrap.appendChild(boxLabel);
    }

    // support tooltip
    if(this.tooltip) {
        this.cbEl.set({qtip:this.tooltip});
    }

    // install event handlers
    this.wrap.on({click:{scope:this, fn:this.onClick, delegate:'a'}});
    this.wrap.on({keyup:{scope:this, fn:this.onClick, delegate:'a'}});

    // restore tabIndex
    this.cbEl.dom.tabIndex = tabIndex;
} // eo function onRender

,onClick:function(e) {
    if(this.disabled || this.readOnly) {
        return;
    }
    if(!e.isNavKeyPress()) {
        this.setValue(!this.checked);
    }
} // eo function onClick

,onDisable:function() {
    this.cbEl.addClass(this.disabledClass);
    this.el.dom.disabled = true;
} // eo function onDisable

,onEnable:function() {
    this.cbEl.removeClass(this.disabledClass);
    this.el.dom.disabled = false;
} // eo function onEnable

,setValue:function(val) {
    if('string' == typeof val) {
        this.checked = val === this.submitOnValue;
    }
    else {
        this.checked = !(!val);
    }

    if(this.rendered && this.cbEl) {
        this.updateHidden();
        this.cbEl.removeClass([this.offCls, this.onCls]);
        this.cbEl.addClass(this.checked ? this.onCls : this.offCls);
    }
    this.fireEvent('check', this, this.checked);

} // eo function setValue

,updateHidden:function() {
    this.el.dom.value = this.checked ? this.submitOnValue : this.submitOffValue;
} // eo function updateHidden

,getValue:function() {
    return this.checked;
} // eo function getValue

}); // eo extend

// register xtype
Ext.reg('xcheckbox', Ext.ux.form.XCheckbox);

 // eo file 

您还需要一些用于新复选框的 CSS:

.xcheckbox-wrap {
 line-height: 18px;
 padding-top:2px;
}
.xcheckbox-wrap a {
 display:block;
 width:16px;
 height:16px;
 float:left;
}
.x-toolbar .xcheckbox-wrap {
 padding: 0 0 2px 0;
}
.xcheckbox-on {
 background:transparent url(../javascripts/ext/resources/images/default/menu/checked.gif) no-repeat 0 0;
}
.xcheckbox-off {
 background:transparent url(../javascripts/ext/resources/images/default/menu/unchecked.gif) no-repeat 0 0;
}
.xcheckbox-disabled {
 opacity: 0.5;
 -moz-opacity: 0.5;
 filter: alpha(opacity=50);
 cursor:default;
}

最后,您可能希望修复 ext-scaffold 以生成这些新的用于布尔值的 xcheckboxes 并且不生成隐藏字段。我修改了 ext_scaffold_panel.js 如下:

    baseParams: scaffoldPanel.baseParams,
    items: [
<%= attributes.inject([]) do |items, a|
 item =  "        { fieldLabel: scaffoldPanel.labels['#{class_name.demodulize.underscore}[#{a.name}]']"
 item << ", name: '#{class_name.demodulize.underscore}[#{a.name}]'"
 item << case a.field_type
   when :text_field      then [:integer, :float, :decimal].include?(a.type) ? ", xtype: 'numberfield'" : ", xtype: 'textfield'"
   when :text_area       then ", xtype: 'textarea'"
   when :date_select     then ", xtype: 'xdatefield'"
   when :datetime_select then ", xtype: 'xdatetime'"
   when :check_box       then ", xtype: 'xcheckbox', inputValue: '1' //// }, { xtype: 'hidden', name: '#{class_name.demodulize.underscore}[#{a.name}]', value: '0'"
 end
 item << " }"
 items << item
end.join(",\n")
%>
    ],

希望这可以帮助其他为此苦苦挣扎的人!

于 2009-08-13T16:03:07.363 回答