Pergunta

Eu estou experimentando com o uso ext_scaffold para gerar elementos de UI para uma aplicação web Rails-backed.

No entanto, estou tendo problemas com o comportamento dos campos boolean. Por exemplo, quando eu faço

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

Ele constrói a migração corretamente e gera uma interface de usuário com uma caixa de seleção para o campo booleano.

Se assinalar esta opção, no entanto, apenas modifica o objeto se ele está sendo criado. Se o registro já existe, o estado da caixa de seleção reflete com precisão o campo. No entanto, a edição está falhando -. Ou seja, marcando ou desmarcando-lo e salvar o registro não mudá-lo

Mergulhando no código, encontramos:

 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' }
    ],

Eu sinto o problema é que tanto Rails ou Ext está confuso com os elementos com nomes idênticos. De qualquer maneira, depois de um registro foi criado, clicando na caixa de seleção não faz nada (marcada ou desmarcada, os '0'. Restos de campo)

Depois de brincar um pouco com isso, acaba por se colocar nesse campo escondido ACIMA a caixa de seleção, não importa o que o campo agora fica definido para true após a edição. Não comportamento exatamente desejado tanto.

Tem mais alguém experimentou este problema? Há soluções alternativas? Obrigado.

UPDATE:

Note que, mesmo com a caixa de seleção para o campo marcado, o pedido enviado POST indica o campo é definido como falso. Todos os outros tipos de campo estão sendo atualizado de forma adequada ...

UPDATE2:

Tudo bem, encontrei um grande post descrevendo a solução da Semergence para este problema , mas eu ainda não sou muito capaz de chegar a este trabalho ... Eu adaptei a sua solução da seguinte forma:

   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);  
   },

Agora o alerta é jogado corretamente, indicando o campo correto e afirmando que será definido como zero.

Exceto isso não ocorre para baixo na solicitação post que na verdade é enviado -. Na verdade, se a caixa de seleção estiver desmarcada, ele não tem um valor no POST em tudo

Alguém pode me ajudar a entender o que está acontecendo aqui?

Foi útil?

Solução

OK, acontece que este é um bug conhecido com o quadro Ext. Andar até os fóruns ExtJS Se você está tendo o mesmo problema, várias soluções descritas lá. O mais simples de implementar é apenas para estender a classe caixa:

# 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 

Você também vai precisar de algum css para as novas caixas de seleção:

.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;
}

Finalmente, você pode querer correção ext-andaime para gerar esses novos xcheckboxes para booleans e também para não gerar o campo escondido. Eu modifiquei ext_scaffold_panel.js da seguinte forma:

    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 isso ajude ninguém lutando com isso!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top