Boolesche Felder in Ext oder Ext_scaffold gebrochen?
-
13-09-2019 - |
Frage
Ich experimentiere mit ext_scaffold mit UI-Elemente für eine Rails-backed Web-Anwendung zu erzeugen.
Allerdings erlebe ich Probleme mit dem Verhalten von Booleschen Feldern. Zum Beispiel, wenn ich
./script/generate ext_scaffold product name:string description:text sku:integer available:boolean
Es baut die Migration ordnungsgemäß und erzeugt eine Benutzeroberfläche mit einem Kontrollkästchen für das boolean Feld.
Wenn dieses Feld aktiviert, jedoch ändert nur das Objekt, wenn es erstellt wird ist. Wenn der Datensatz bereits vorhanden ist, spiegelt der Zustand der Checkbox genau das Feld. Es ist jedoch versagt Bearbeitung - d. H, die Überprüfung oder es und speichern Sie die Aufzeichnung unchecking es nicht ändern
Dipping in den Code, finden wir:
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' }
],
Ich habe das Gefühl das Problem ist, dass entweder Rails oder Ext bei den identisch genannten Elementen verwechselt wird. So oder so, nachdem ein Datensatz erstellt wurde, klicken Sie das Kontrollkästchen tut nichts (aktiviert oder deaktiviert, das Feld bleibt ‚0‘).
Nachdem sie mit dieser ein wenig herum zu spielen, stellt sich heraus, wenn wir setzen, dass versteckte Feld über dem Kontrollkästchen, egal, was das Feld nun auf true gesetzt wird nach der Bearbeitung. Nicht gerade Verhalten entweder gewünscht wird.
Hat jemand dieses Problem erfahren? Gibt es Workarounds? Danke.
UPDATE:
Hinweis, dass auch mit dem Kontrollkästchen für das Feld überprüft, schickte die POST-Anforderung anzeigt, wird das Feld auf false gesetzt. Alle anderen Feldtypen werden immer entsprechend aktualisiert ...
UPDATE2:
In Ordnung, fand eine große Blog-Post Semergence Lösung für dieses Problem beschreiben, aber ich bin noch nicht ganz in der Lage zu bekommen dies funktioniert ... ich habe seine Lösung wie folgt angepasst:
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);
},
Nun wird die Warnung richtig geworfen, das richtige Feld angibt, und behauptet wird es auf Null gesetzt werden.
Außer dies nicht der Fall nach unten in der Post-Anforderung, die tatsächlich bekommt geschickt -. In der Tat, wenn das Kontrollkästchen nicht markiert ist, es keinen Wert in der POST überhaupt haben
Kann mir jemand helfen, zu verstehen, was hier vor sich geht?
Lösung
OK, stellt sich heraus, das ist ein bekannter Fehler mit dem Ext-Framework. Schlendern Sie über den ExtJS Foren, wenn Sie das gleiche Problem haben sollten, mehrere Lösungen gibt skizziert. Die einfachste zu implementieren, ist nur die Checkbox Klasse zu erweitern:
# 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
Sie werden auch einige CSS für das neue Kontrollkästchen müssen:
.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;
}
Schließlich können Sie ext-Gerüst zu beheben, diese neuen xcheckboxes für booleans zu erzeugen und auch das versteckte Feld nicht zu erzeugen. Ich veränderte ext_scaffold_panel.js wie folgt:
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")
%>
],
Hope, das hilft jemand anderes mit diesem zu kämpfen!