Boolean Les champs cassés Ext ou Ext_scaffold?
-
13-09-2019 - |
Question
J'expérimente l'utilisation ext_scaffold pour générer des éléments de l'interface utilisateur pour une application Web soutenu par Rails.
Cependant, je rencontre des problèmes avec le comportement des champs booléens. Par exemple, quand je fais
./script/generate ext_scaffold product name:string description:text sku:integer available:boolean
Il construit la migration correctement et génère une interface utilisateur avec une case à cocher pour le champ booléen.
Si vous cochez cette case, cependant, ne modifie l'objet si elle est en cours de création. Si l'enregistrement existe déjà, l'état de la case à cocher reflète avec précision le champ. Cependant, l'éditer échoue -. À savoir, la vérification ou décochant et sauvegarde de l'enregistrement ne change pas
trempant dans le code, nous trouvons:
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' }
],
Je sens le problème est que soit Rails ou Ext est confondu les éléments nommés de manière identique. De toute façon, après un enregistrement a été créé, cliquez sur la case à cocher ne fait rien (enregistré ou non, le champ reste « 0 »).
Après avoir joué un peu avec cela, il se trouve si l'on place ce champ Cachée la case à cocher, quel que soit le champ se maintenant à true après l'édition. Pas exactement soit le comportement souhaité.
Quelqu'un at-il rencontré ce problème? Y a-t-il des solutions de contournement? Merci.
Mise à jour:
Notez que même avec la case à cocher pour le champ cochée, la requête POST envoyée indique que le champ est défini sur false. Tous les autres types de champs sont mis à jour de façon appropriée se ...
MAJ2:
D'accord, a trouvé un grand blog décrivant la solution à ce problème Semergence , mais je ne suis toujours pas tout à fait en mesure d'obtenir ce travail ... Je l'ai adapté sa solution comme suit:
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);
},
Maintenant, l'alerte est jeté correctement, indiquant le champ approprié et d'affirmer qu'il sera mis à zéro.
Sauf que cela ne se produit pas dans la demande de poste qui obtient effectivement envoyé -. En fait, si la case est cochée, il n'a pas de valeur dans le POST du tout
Quelqu'un peut-il me aider à comprendre ce qui se passe ici?
La solution
OK, se c'est un bug connu avec le framework Ext. Promenez-vous sur les forums ExtJS si vous rencontrez le même problème, plusieurs solutions qui y sont décrites. Le plus simple à mettre en œuvre est juste pour étendre la classe de case à cocher:
# 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
Vous aurez également besoin d'css pour les nouvelles cases à cocher:
.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;
}
Enfin, vous pouvez fixer poste-échafaudage pour générer ces nouveaux xcheckboxes pour booléens et aussi de ne pas générer le champ caché. Je modifié ext_scaffold_panel.js comme suit:
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")
%>
],
Espérons que cela aide tout le monde en difficulté d'autre avec cela!