2009-02-26 7 views
29

Vorrei rendere i campi dei moduli di modifica il più user-friendly possibile. Ad esempio, per valori numerici, vorrei che il campo fosse visualizzato con virgole (come number_with_precision).Come posso formattare il valore mostrato nel campo di modifica di Rails?

Questo è abbastanza facile sul lato del display, ma per quanto riguarda la modifica? C'è un buon modo per farlo?

Sto utilizzando il modulo Rails FormBuilder. Dopo un'indagine, ho scoperto che utilizza InstanceTag, che ottiene i valori per i campi usando <attribute>_value_before_type_cast, il che significa che l'override di <attribute> non verrà richiamata.

+0

ho iniziato una taglia su questa domanda, perché voglio sapere se c'è un risposta migliore di quelle articolate da JDL e da me. Abbi! –

risposta

37

Il migliore che ho elaborato finora è qualcosa di simile:

<%= f.text_field :my_attribute, :value => number_with_precision(f.object.my_attribute) %> 

O my_attribute potrebbe restituire il valore formattato, in questo modo:

def my_attribute 
    ApplicationController.helpers.number_with_precision(read_attribute(:my_attribute)) 
end 

Ma si devono ancora utilizzare :value

<%= f.text_field :my_attribute, :value => f.object.my_attribute %> 

Questo sembra un sacco di lavoro.

+0

Nota: se si utilizza la prima soluzione con un formato che aggiunge virgole o simboli di valuta, è necessario eliminarli nei metodi di creazione e aggiornamento del controller. – LeBleu

+0

Eviterei di usare la seconda soluzione, fare riferimento a 'ApplicationController' dal tuo modello non è sicuramente una buona cosa per abituarsi a farlo. –

+0

L'ultimo ha funzionato meglio per me, le mie funzioni potrebbero ancora essere nel mio modello di dati e non influisce sull'invio o la modifica. Bella soluzione! –

9

Preferisco la prima risposta, con la formattazione eseguita nella vista. Tuttavia, se si desidera eseguire la formattazione nel modello, è possibile utilizzare i metodi wrapper per getter e setter ed evitare di utilizzare interamente l'opzione: value.

Si finirebbe con qualcosa di simile.

def my_attribute_string 
    foo_formatter(myattribute) 
end 

def my_attribute_string=(s) 
    # Parse "s" or do whatever you need to with it, then set your real attribute. 
end 

<%= f.text_field :my_attribute_string %> 

Railscasts coperto questo con un oggetto Tempo in un text_field in episode #32. La parte davvero intelligente di questo è il modo in cui gestiscono gli errori di convalida. Vale la pena guardare l'episodio solo per quello.

3

Se si desidera creare o mantenere un formato durante la modifica, sarà necessario aggiungere Javascript per implementare "maschere". Here is a demo.

È stato il primo hit in these results.

+0

Demo non c'è più, eccone uno nuovo: https://igorescobar.github.io/jQuery-Mask-Plugin/ – fatfrog

1

Ho fatto qualcosa di simile. Formiamo tempi e lunghezze utilizzando un generatore di moduli personalizzato. Si fa uso del text_field esistente, ma avvolge in modo che il valore può essere personalizzato:

class SuperFormBuilder < ActionView::Helpers::FormBuilder 
    include ApplicationHelper 
    include FormHelper 
    include ActionView::Helpers::TagHelper 
    include ActionView::Helpers::FormTagHelper 

    def length_field(label,*args) 
    scale = 'medium' 
    args.each do |v| 
     if v.has_key?(:scale) 
     scale = v[:scale] 
     v.delete(:scale) 
     end 
    end 
    value = length_conversion(@object.send(label.to_sym),scale) 
    options = (args.length > 0) ? args.pop : {} 
    return has_error(label, text_field_tag(field_name(label),value,*args) + ' ' + length_unit(scale)) 
end 

private 
def field_name(label) 
    return @object_name + "[#{label}]" 
end 

def has_error(label, output) 
    return "<div class='fieldWithErrors'>#{output}</div>" if @object.errors[label] 
    return output 
end 

Ed è usato in questo modo:

<%= form_for(@section, {:action => 'save', :id => @section.id}, :builder => SuperFormBuilder) do |sf| %> 
    <%= sf.length_field :feed_size_min_w, :size => 3, :scale => 'small' %> 
<% end %> 

Il risultato finale è un valore nell'unità appropriata in base dalla loro scelta su sistema (Metrico, Imperiale) e scala IE piccolo = pollici o millimetri.

Ho praticamente copiato il metodo text_field dal generatore di moduli esistente, che utilizza lo stesso text_field_tag.

Ci sono due trucchi: 1) Conoscere il nome del campo dell'oggetto e come accedere all'oggetto per ottenere il valore che si desidera formattare. 2) Ottenere il nome giusto così quando il modulo viene inviato è parte dell'hash params corretto.

Al generatore di moduli viene assegnata una variabile di classe @object. Puoi ottenere il valore del campo usando il metodo .send.Nel mio caso mando l'etichetta: feed_size_min_w a @object e riprendo la sua lunghezza. Poi lo converto nel mio formato desiderato e lo do al text_field_tag.

Il nome del campo è la chiave per averlo finito nell'hash params, nel mio caso il params [: sezioni] uno. Ho creato una piccola funzione di aiuto chiamata field_name che si occupa di questo.

Infine has_error racchiude il campo in un errore div se vi sono errori su tale etichetta.

3

È possibile utilizzare il plug-in number_format. Specificando uno number_format per un attributo numerico esistente all'interno del modello, l'attributo verrà ora formattato come Rails in tutte le maschere e viste. Verrà inoltre analizzato da quel formato (se assegnato tramite moduli) prima dell'inserimento nel database. (Il plugin crea anche puramente numerici unformatted_<attribute-name> di accesso che possono continuare ad essere utilizzati per l'aritmetica, o per l'assegnazione numerica diretta o il recupero da voi per una perfetta integrazione.)

class MyModel < ActiveRecord::Base 
    # this model has the balance attribute, which we 
    # want to display using formatting in views, 
    # although it is stored as a numeric in the database 
    number_format :balance, 
       :precision => 2, 
       :delimiter => ',', 
       :strip_trailing_zeros => false 

    def increment_balance 
    unformatted_balance += 10 
    end 

È inoltre possibile combinare quanto sopra con una soluzione di Javascript, che può costringere l'utente a mantenere il punto decimale e le migliaia di separatori sul posto durante la modifica, sebbene ciò non sia realmente necessario.

+0

Buona idea. Non funziona su Rails 3 come ho provato oggi. – Cheng

4

Questa è una vecchia domanda, ma nel caso in cui qualcuno si imbatta in questo, è possibile utilizzare gli helper number_to_X. Essi hanno tutti gli attributi che si possa desiderare per la visualizzazione vostro valore edit:

<%= f.text_field :my_number, :value => number_to_human(f.object.my_number, :separator => '', :unit => '', :delimiter => '', :precision => 0) %> 

Non ci sono più attributi disponibili anche: http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html

Problemi correlati