Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Correct way of working with ViewModels and Form/Fieldset
  • Hey, I've got a setup which uses ViewModels but I keep moving code back to the controller all the time... I think I need a short primer on the 'correct' way for this to work. I want to have a Fieldset built form on the end view, I create it first up in my ViewModel and everything's dandy. Then I add the Edit view and I need to repopulate the Fieldset with the entry data, or validate it before I put it into the db. However I try to jump through hoops I end up with the Fieldset code in the controller. And thus also all the code to generate dropdowns and whatnot for the different fields... What is your code structure for working with Fieldset? Thanks for reading,
    /Andy
  • You need to define the fieldset in your controller, because thats where you have to do the validation and where the processing of the validated fieldset is. The rest can go into the Viewmodel without problems, just pass the fieldset object to it, have it pass it on to the view, and in the view call the build() method. The generic edit method for fieldsets is something like this:
     /**
      * edit action: edit a person
      *
      * @param   $id id of the person record to edit
      * @throws  none
      * @returns void
      */
     public function action_edit($id = null)
     {
      // edit cancelled?
      \Input::post('cancel', false) !== false and \Response::redirect('mymodule/people');
    
      // get the user record we want to edit
      if ( ! $people = Model\Person::find($id))
      {
       // bail out with an error if not found
       \Messages::error(__('people.not-found'));
       \Response::redirect('mymodule/people');
      }
    
      // create the model fieldset
      $form = \Fieldset::forge('form');
      $form->add_model('Mymodule\\Model\\Person');
    
      // do we have input?
      if (\Input::post())
      {
       // validate the input
       $form->validation()->run();
    
       // if validated, save the updates
       if ( ! $form->validation()->error())
       {
        // get the validated data, and get rid of null values
        $data = array_filter($form->validated(), function($item){ return $item !== null; });
    
        // custom data processing here...
    
        // update the people record
        $people->from_array($data);
    
        // and save it
        if ($people->save())
        {
         \Messages::success(sprintf(__('people.updated'), $people->surname.', '.$people->initials.' '.$people->prefix));
         \Response::redirect('mymodule/people');
        }
        else
        {
         \Messages::error(__('people.updated-failed'));
        }
       }
       else
       {
        // inform the user validation failed
        \Messages::error(__('people.form.errors'));
       }
    
       // repopulate the form from the posted data
       $form->repopulate();
      }
      else
      {
       // populate the form with the existing data
       $form->populate($people);
      }
    
      // return the view and pass our fieldset
      return \Viewmodel::forge('people/edit')->set('form', $form, false);
     }
    

    I would have a theme set_partial instead of the Viewmodel there, but the flow remains the same. For a create method, create a new Model object instead of looking one up, and remove the initial $form->populate(); call (or replace it by initial form population). The rest of the flow is identical. The Messages class is my generic class for dealing with application messages, and is basically a wrapper around Session::set_flash() with some added functionality like different message types, output them ordered by type, etc.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion