Wednesday, April 13, 2016

How to prepopulate _form for featured objects?

Leave a Comment

A user can input a custom :action or choose a featured :action:

<%= f.text_field :action %>   Or choose a featured challenge: <%= f.collection_radio_buttons :action, [['Run a Mile','Run a Mile'], ['Drink 16oz of Water','Drink 16oz of Water'], ['Take a Picture','Take a Picture'], ['1 Drink Max','1 Drink Max'], ['See Eiffel Tower','See Eiffel Tower'], ['Write a Book','Write a Book'], ['Skydive','Skydive'], ['Start a Business','Start a Business'], ['No Snooze','No Snooze'], ['Visit All 50 States','Visit All 50 States'], ['Talk to a Stranger','Talk to a Stranger'], ['Try a New Recipe','Try a New Recipe'], ['Media-fast','Media-fast']], :first, :last %> 

If a user chooses a featured :action the new challenges/_form is pre-populated with his chosen :action, but now I'd like to take it to the next level with your help!

<%= form_for(@challenge)  do |f| %>   Challenge: <%= f.text_field :action %>   Do On: <%= f.collection_check_boxes :committed %>   Do For: <%= f.number_field :days_challenged %> <% end %> 

How can I pre-populate the other attributes of a featured challenge like, "Do For" or "Do On"?

For example if a user chose the featured :action: 'Run a Mile then I would pre-populate the form with Run a Mile, Mon, Wed, Fri, 30 Days.

UPDATE

challenges_controller

class ChallengesController < ApplicationController   before_action :set_challenge, only: [:show, :edit, :update, :destroy, :challenging, :mark_accomplished, :mark_completed, :create_freebie, :like]   before_action :populate_challenge, only: [:create]   respond_to :html, :json    # User chooses featured challenge action or creates custom challenge action here   def new     @challenge = Challenge.new     respond_modal_with @challenge, location: root_path   end    # User is then redirected to create.html.erb where we can input the other attributes of the object.   def create     @challenge = Challenge.new(challenge_params)     @form = ChallengeForm.new(@challenge)     if params[:step] == '2'       @challenge = current_user.challenges.build(challenge_params)       @challenge.save       redirect_to @challenge     end   end  private   def populate_challenge     require "reform/form/dry"      Reform::Form.class_eval do        feature Reform::Form::Dry      end   end    def set_challenge     @challenge = Challenge.find(params[:id])   end    def challenge_params     params.require(:challenge).permit(       :action,       :category,       :deadline,        :date_started,       :days_challenged,       :send_email => [],       :committed => [])   end end 

1 Answers

Answers 1

You can use simple_form with reform. Reform will give you form object, where you can override methods that will populate your form.

Here is a watered-down example (you will have to adjust it to your case):

class ChallengeForm < Reform::Form   property :action   property :committed   property :days_challenged    model :challenge    def commited     super || action_to_commited_hash[model.action]   end    def days_challenged     super || action_to_days_challenged_hash[model.action]   end    def action_to_days_challenged_hash     {       'Run a Mile' => 30,       'Take a Picture' => 12     }   end    def action_to_commited_hash     {       'Run a Mile' => ['Mon', 'Wed', 'Fri'],       'Take a Picture' => ['Tu', 'Thu']     }   end end 

super in the methods above will delegate to the model. Note that you are overriding getter methods, and it doesn't affect setters (you can override setters too if you wanted to change form data before writing it).

In your template, instead of

form_for @challenge 

you will have:

simple_form_for @form 

It's a super common form library for Rails and I can't imagine not using it myself!

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment