Skip to content

Latest commit

 

History

History

Fields

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Fields

This library gives you the tools to create your own custom fields. By extending the base Field class, your field can be easily used in any form you build. And the best part is that you still have complete control over how it looks and feels.

Creating a field

To learn how to create a field, let's work together on a new type of field that allows the user to submit their age in years. This is a nice, simple example that will require some validation.

When we finish, usage of this new field will be as easy as:

$form->age('age')->label('Age')->required();

age

Let's get started!

Folder Structure

In the same namespace (or folder) that you created your form in Step 1, create a folder called Fields. For example path/to/my/app/forms/Fields. Next, inside the folder we just created, create another folder called Age that will contain everything for our new field - like so path/to/my/app/forms/Fields/Age.

Class

Create a class named Age that extends Helmut\Forms\Field.

// File: path/to/my/app/Forms/Fields/Age/Age.php

namespace App\Forms\Fields\Age;

use \Helmut\Forms\Field;

class Age extends Field {
    

}

Because you are extending Helmut\Forms\Field there will be a few abstract methods that you will need to implement. Let's walk through each one below

  1. The getValue method returns the current value of the field (fancy that eh?). It is up to you to define how the field stores it's current value. In this case we'll add a property to the class to hold the current value and return it using the getValue method.

    protected $value = '';
    
    public function getValue()
    {
        return $this->value;
    }
  2. The getButtonName method returns the name of any keys that are associated with buttons that can submit the form. As this field does not contain any buttons we don't have to do anything other than implement an empty method.

    public function getButtonName()
    {
        
    }
  3. The renderWith method should return an array of properties to be passed to the template when rendering. The only property we have at the moment is value so let's just return that. Other properties such as id, form_id, name, type, label, required, valid and invalid are included automatically.

    public function renderWith()
    {
        return ['value' => $this->value];
    }
  4. The setValueFromDefault method is used to set the current value of the field using any defaults that have been set. By extending Helmut\Forms\Field we have access to a default property that contains specified default values. Defaults can be set when your field is created - for example $form->age('age')->default(18). This method is only called if a default has actually been set, so you can be sure that $this->default contains a value.

    public function setValueFromDefault()
    {
        $this->value = $this->default;        
    }
  5. The setValueFromModel method is used to set the current value of the field using a model. So to implement this method we really just want to check if the passed in model has the same name property as the field and then set the value accordingly. The name of our field is a property of the parent class and can be retrieved using $this->name.

    public function setValueFromModel($model)
    {
        if (isset($model->{$this->name})) $this->value = $model->{$this->name};
    }  
  6. The setValueFromRequest method is used to set the current value of the field using the request object. Fetch the value for this field out of the request (using the name again) and set it. For details about the request object check out the Request interface.

    public function setValueFromRequest($request)
    {
        $this->value = $request->get($this->name);
    }  
  7. The fillModelWithValue method is the opposite of the setValueFromModel. Take this field's value and fill the matching property of the model with it.

    public function fillModelWithValue($model)
    {
        if (isset($model->{$this->name})) $model->{$this->name} = $this->value;
    }  
  8. The validate method is where you can add any validation methods that need to run by default. For many fields there are no default validations needed so you can simply ignore. However in this case we want make sure the response is always numeric and no less than zero. Here you can see we added two new validation methods and called them from the validate method.

    public function validate()
    {
        $this->numeric()->min(0);
    }  
    
    public function validateNumeric()
    {
        return  is_numeric($this->value);
    }
    
    public function validateMin($number)
    {
        return $this->value > 0;
    }          
  9. The validateRequired method is the only validation that you are forced to implement. We can just check that the value property is not empty.

    public function validateRequired()
    {
        return ! empty($this->value);
    }  

So your full Age class should look like this:

namespace App\Forms\Fields\Age;

use \Helmut\Forms\Field;

class Age extends Field {

    protected $value = '';

    public function getValue()
    {
        return $this->value;
    }

    public function getButtonName()
    {

    }

    public function renderWith()
    {
        return ['value' => $this->value];
    }

    public function setValueFromDefault()
    {
        $this->value = $this->default;
    }

    public function setValueFromModel($model)
    {
        if (isset($model->{$this->name})) $this->value = $model->{$this->name};
    }

    public function setValueFromRequest($request)
    {
        $this->value = $request->get($this->name);
    }

    public function fillModelWithValue($model)
    {
        if (isset($model->{$this->name})) $model->{$this->name} = $this->value;
    }
    
    public function validate()
    {
        $this->numeric();
    }  

    public function validateNumeric()
    {
        return  is_numeric($this->value);
    }

    public function validateRequired()
    {
        return ! empty($this->value);
    }    

}

Template

Create a folder called templates for your age field - path/to/my/app/forms/Fields/Age/templates. Then create a subfolder with the same name as your theme. So if we are using the default theme, the folder will be called bootstrap - path/to/my/app/forms/Fields/Age/templates/bootstrap.

Add a new template file named age.mustache.php. Templates can be rendered by specifying the engine in the filename extension. For example age.mustache.php will use the Mustache engine. Twig and Blade are also available.

// File: path/to/my/app/Forms/Fields/Age/templates/bootstrap/age.mustache.php

<div class="row">
    <div class="col-sm-12">
        <div class="form-group" style="margin-bottom:10px">
            <label>{{ label }}{{# required }} <span style="font-weight:normal" title="{{ lang.required }}">*</span>{{/ required}}</label>
            <input name="{{ name }}" value="{{ value }}" type="text" class="form-control" style="width:25%">
        </div>
    </div>
</div>

As you can see, you have full control over how the field is rendered.

Try it out

We're almost finished! But let's try out this new age field before we continue.

// Build the form
$form = new App\Forms\Form;

// Define the new field
$form->age('age')->label('Age')->required();

// Render
echo $form->render();

age

Not bad hey!

Additional Validation

Don't forget that we also needed to be able to have the option of setting a minimum. For example $form->age('age')->label('Age')->min(21). To create a min(21) validation we need to add a validateMin method to our Age class. All validation methods must be prefixed with the word validate.

public function validateMin($min)
{
    return $this->value >= $min;
}

Format the error message within a language file. Create a folder called lang for your age field - path/to/my/app/forms/Fields/Age/lang. Then create a file for english called en.php - path/to/my/app/forms/Fields/Age/lang/en.php. The error message will be picked up automatically.

return [
    'validate_min' => 'The [field] field must be a minimum of [min].',
];

As you can see, it works!

age-error