SORU
9 Kasım 2009, PAZARTESİ


Mütevazi dinamik bir WordPress kullanmak ile Raylar alanları formu

Bu çerçeve çok incelikle ele gelmez bir şey görünüyor Raylar -- dinamik form alanları engel üzerinden almak için çalışıyorum. Ayrıca projemde jQuery kullanıyorum. JRails kurdum fakat daha ziyade mümkünse AJAX kod göze batmayacak şekilde yazmak istiyorum.

Benim formları oldukça karmaşık, iç içe geçmiş iki veya üç düzeyde bir durum değildir. Yaşıyorum sorun form builder içerik o kadar bağımlı oldukları için doğru formu kimlikleri oluşturuluyor. Yeni alanlar dinamik olarak eklemek veya has_many bir ilişki içinde varolan kayıtları silmek mümkün olmak istiyorum, ve bir kayıp tamamen destekliyorum.

Şu ana kadar gördüğüm her örnek, öyle ya da böyle çirkin oldu. Ryan Bates'in tutorial biçimlendirme oldukça çirkin ve rahatsız edici bazı javascript sonuçları RJS, gerektirir, ve iç içe geçmiş öznitelikleri önce yazılmış gibi görünüyor. Mütevazi jQuery ile örnek fork bir gördüm, ama burada, ve benim projede çalışma fırsatı bulamadık ne anlamıyorum.

Birine bu nasıl yapılır, basit bir örnek verebilir? Bu denetleyicileri Dinlendirici Kongre saygı mümkün mü?


Andy varolan bir kaydı silme mükemmel bir örnek gönderdi, kimseye doğru özelliğe sahip yeni alanlar oluşturma Bir örnek verebilir? İç içe geçmiş formlar ile bunu yapmak için nasıl anlamaya mümkün olmamıştır.

CEVAP
17 Kasım 2009, Salı


Kimse bile bir lütuf sonra buna bir yanıt verdi, yana, sonunda kendim çalıştırmayı başardım. Bunu seni üzmek için söylememiştim! Umarım bu daha kolay Raylar 3.0 yapmak olacak.

Andy'nin örnek doğrudan kayıtları silmek için iyi bir yol, sunucuya bir form vermeden. Bu durumda, gerçekten ne aradığımı dinamik bir yoldur/iç içe bir form için bir güncelleştirme yapmadan önce alanları Kaldır. Bu alanlar çıkarılır, form kadar aslında silinmiş değiller çünkü biraz farklı bir durum. Muhtemelen her ikisi de duruma göre kullanılarak sona erecek.

Github çatal Tim Riley's complex-forms-examples benim uygulama tabanlı ettim.

İlk modeller kurmak ve iç içe geçmiş öznitelikleri destekler emin olun:

class Person < ActiveRecord::Base
  has_many :phone_numbers, :dependent => :destroy
  accepts_nested_attributes_for :phone_numbers, :reject_if => lambda { |p| p.values.all?(&:blank?) }, :allow_destroy => true
end

class PhoneNumber < ActiveRecord::Base
  belongs_to :person
end

Bu PhoneNumber form alanları için kısmi bir görünüm oluşturun:

<div class="fields">
  <%= f.text_field :description %>
  <%= f.text_field :number %>
</div>

Önümüzdeki bir temel İnsan modeli görüntülemek ve düzenlemek yazmak:

<% form_for @person, :builder => LabeledFormBuilder do |f| -%>
  <%= f.text_field :name %>
  <%= f.text_field :email %>
  <% f.fields_for :phone_numbers do |ph| -%>
    <%= render :partial => 'phone_number', :locals => { :f => ph } %>
  <% end -%>
  <%= f.submit "Save" %>
<% end -%>

Bu javascript ile üretebileceğimizi bu PhoneNumber modeli için şablon alanları oluşturarak çalışır. Bunun için app/helpers/application_helper.rb yardımcı yöntemler yaratacağız:

def new_child_fields_template(form_builder, association, options = {})
  options[:object] ||= form_builder.object.class.reflect_on_association(association).klass.new
  options[:partial] ||= association.to_s.singularize
  options[:form_builder_local] ||= :f

  content_tag(:div, :id => "#{association}_fields_template", :style => "display: none") do
    form_builder.fields_for(association, options[:object], :child_index => "new_#{association}") do |f|
      render(:partial => options[:partial], :locals => { options[:form_builder_local] => f })
    end
  end
end

def add_child_link(name, association)
  link_to(name, "javascript:void(0)", :class => "add_child", :"data-association" => association)
end

def remove_child_link(name, f)
  f.hidden_field(:_destroy)   link_to(name, "javascript:void(0)", :class => "remove_child")
end

Şimdi bu yardımcı yöntemler, kısmi düzenlemek için Ekle:

<% form_for @person, :builder => LabeledFormBuilder do |f| -%>
  <%= f.text_field :name %>
  <%= f.text_field :email %>
  <% f.fields_for :phone_numbers do |ph| -%>
    <%= render :partial => 'phone_number', :locals => { :f => ph } %>
  <% end -%>
  <p><%= add_child_link "New Phone Number", :phone_numbers %></p>
  <%= new_child_fields_template f, :phone_numbers %>
  <%= f.submit "Save" %>
<% end -%>

Şimdi js yapılan şablon var. Her ilişki için boş bir şablon sunacak, ama modeli :reject_if yan onları, sadece kullanıcı tarafından oluşturulan alanlar bırakarak iptal edecek.Güncelleme:Yeniden düşündüm bu tasarım, aşağıda neler olduğunu görmek istiyorum.

Herhangi bir iletişim sayfası yük ötesinde sunucu ve formu gönder gitmeyi olmadığına göre bu gerçekten AJAX değil, ama ben dürüst olup bittikten sonra bunu yapmak için bir yol bulamadı.

Aslında bu işin bitene kadar her ek alan için sunucu yanıtı için beklemek zorunda değilsiniz bu yana, daha iyi bir kullanıcı deneyimi sunmak AJAX daha olabilir.

Son olarak bu javascript ile Tel ihtiyacımız var. Aşağıdaki `public/javascripts/application.js' Dosya: Ekle

$(function() {
  $('form a.add_child').click(function() {
    var association = $(this).attr('data-association');
    var template = $('#'   association   '_fields_template').html();
    var regexp = new RegExp('new_'   association, 'g');
    var new_id = new Date().getTime();

    $(this).parent().before(template.replace(regexp, new_id));
    return false;
  });

  $('form a.remove_child').live('click', function() {
    var hidden_field = $(this).prev('input[type=hidden]')[0];
    if(hidden_field) {
      hidden_field.value = '1';
    }
    $(this).parents('.fields').hide();
    return false;
  });
});

Bu zamana kadar işlemci dinamik bir form olmalı! Javascript burada çok basit ve kolayca diğer çerçeveler ile yapılabilir. Kolayca örneğin prototip lowpro application.js benim kod. Temel fikir, biçimlendirme içine devasa javascript fonksiyonları gömme olmadığını ve modelleri phone_numbers=() sıkıcı fonksiyonları yazmak zorunda değilsin. Her şey çalışıyor. Yaşasın!


Bazı testlerden sonra şablonlar <form> alanların taşındı gerekir sonucuna vardım. Onları orada tutmak sunucuya geri formun geri kalanı ile gönderilir anlamına gelir, ve o sadece sonra baş ağrısı oluşturur.

Benim düzen altına bunu ekledim:

<div id="jstemplates">
  <%= yield :jstemplates %>
</div

Ve değiştirilmiş new_child_fields_template yardımcı:

def new_child_fields_template(form_builder, association, options = {})
  options[:object] ||= form_builder.object.class.reflect_on_association(association).klass.new
  options[:partial] ||= association.to_s.singularize
  options[:form_builder_local] ||= :f

  content_for :jstemplates do
    content_tag(:div, :id => "#{association}_fields_template", :style => "display: none") do
      form_builder.fields_for(association, options[:object], :child_index => "new_#{association}") do |f|        
        render(:partial => options[:partial], :locals => { options[:form_builder_local] => f })        
      end
    end
  end
end

Şimdi modelleri :reject_if maddeleri kaldırmak ve şablonları geri gönderilme endişesi durdurabilirsiniz.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • ArkticPlanet

    ArkticPlanet

    9 ŞUBAT 2010
  • Awesomesauce Network

    Awesomesauce

    4 EKİM 2012
  • rekjavicxxx

    rekjavicxxx

    28 EKİM 2007