Los campos de Boole roto en Ext o Ext_scaffold?
-
13-09-2019 - |
Pregunta
Estoy experimentando con el uso de ext_scaffold para generar elementos de la interfaz de usuario para una aplicación web apoyado por los carriles.
Sin embargo, tengo problemas con el comportamiento de los campos booleanos. Por ejemplo, cuando hago
./script/generate ext_scaffold product name:string description:text sku:integer available:boolean
Se construye la migración correctamente y genera una interfaz de usuario con una casilla de verificación para el campo booleano.
Al marcar esta casilla, sin embargo, sólo se modifica el objeto si está siendo creado. Si el registro ya existe, el estado de la casilla refleja con precisión el campo. Sin embargo, la edición está fallando -. Es decir, activando o desactivando y guardar el registro no lo cambia
Inmersión en el código, nos encontramos con:
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' }
],
Siento el problema es que cualquiera de los carriles o Ext se confunde a los elementos con nombres idénticos. De cualquier manera, después de un registro se ha creado, haga clic en la casilla de verificación no hace nada (activada o desactivada, el campo sigue siendo '0'.)
Después de jugar un poco con esto, resulta que si colocamos un campo oculto ARRIBA la casilla de verificación, no importa lo que el campo ahora se establece en true después de la edición. No es exactamente el comportamiento deseado, ya sea.
¿Alguien más ha tenido este problema? ¿Hay alguna solución? Gracias.
ACTUALIZACIÓN:
Tenga en cuenta que incluso con la casilla de verificación para el campo está marcado, la solicitud POST envía indica que el campo se establece en false. Todos los demás tipos de campo están siendo actualizados apropiadamente ...
Update2:
De acuerdo, se encontró una gran entrada de blog que describe la solución de este problema Semergence a , pero todavía no estoy del todo capaz de conseguir que esto funcione ... me he adaptado su solución de la siguiente manera:
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);
},
Ahora la alerta es lanzado correctamente, indicando el campo correcto y afirmando que se establece en cero.
Excepto esto no ocurre en la solicitud de cargo que realmente se ha enviado -. De hecho, si la casilla de verificación no está marcada, que no tiene un valor en el POST en absoluto
Puede alguien ayudarme a entender lo que está pasando aquí?
Solución
bien, resulta que esto es un error conocido con el marco Ext. Pasear a los foros ExtJs si va a tener el mismo problema, varias soluciones describen allí. El más simple de implementar es sólo para extender la clase casilla de verificación:
# 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
Usted también necesitará un poco de CSS para las nuevas casillas de verificación:
.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;
}
Por último, es posible que desee fijar ext-andamio para generar estos nuevos xcheckboxes para booleanos y tampoco para generar el campo oculto. He modificado ext_scaffold_panel.js como sigue:
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")
%>
],
Espero que esto ayude a nadie más que luchan con esto!