Transforming data with view models | laravel-blade-x | Spatie

 SPATIE

laravel-blade-x
===============

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-blade-x](https://spatie.be/docs/laravel-blade-x/v2)  Advanced-usage  Transforming data with view models

 Version   v2

 Other versions for crawler [v2](https://spatie.be/docs/laravel-blade-x/v2)

- [ Introduction ](https://spatie.be/docs/laravel-blade-x/v2/introduction)
- [ Postcardware ](https://spatie.be/docs/laravel-blade-x/v2/postcardware)
- [ Requirements ](https://spatie.be/docs/laravel-blade-x/v2/requirements)
- [ Installation &amp; setup ](https://spatie.be/docs/laravel-blade-x/v2/installation-setup)
- [ Questions and issues ](https://spatie.be/docs/laravel-blade-x/v2/questions-issues)
- [ Changelog ](https://spatie.be/docs/laravel-blade-x/v2/changelog)
- [ Upgrading ](https://spatie.be/docs/laravel-blade-x/v2/upgrading)
- [ About us ](https://spatie.be/docs/laravel-blade-x/v2/about-us)

Basic usage
-----------

- [ Writing your first component ](https://spatie.be/docs/laravel-blade-x/v2/basic-usage/writing-your-first-component)
- [ Using variables ](https://spatie.be/docs/laravel-blade-x/v2/basic-usage/using-variables)
- [ Using slots ](https://spatie.be/docs/laravel-blade-x/v2/basic-usage/using-slots)

Advanced usage
--------------

- [ Transforming data with view models ](https://spatie.be/docs/laravel-blade-x/v2/advanced-usage/transforming-data-with-view-models)
- [ Sharing data with context ](https://spatie.be/docs/laravel-blade-x/v2/advanced-usage/sharing-data-with-context)
- [ Prefixing components ](https://spatie.be/docs/laravel-blade-x/v2/advanced-usage/prefixing-components)

Under the hood
--------------

- [ From BladeX to Blade ](https://spatie.be/docs/laravel-blade-x/v2/under-the-hood/from-bladex-to-blade)

 Transforming data with view models
==================================

Before rendering a BladeX component you might want to transform the passed data, or add inject view data. You can do this using a view model. Let's take a look at an example where we render a `select` element with a list of countries.

To make a BladeX component use a view model, pass a class name to the `viewModel` method.

```
BladeX::component('select-field')->viewModel(SelectFieldViewModel::class);
```

Before reviewing the contents of the component and the view model itself, let's take a look at the `select-field` component in use.

```
@php
// In a real app this data would probably come from a controller
// or a view composer.
$countries = [
    'be' => 'Belgium',
    'fr' => 'France',
    'nl' => 'The Netherlands',
];
@endphp

```

Next, let's take a look at the `SelectFieldViewModel::class`:

```
class SelectFieldViewModel extends ViewModel
{
    /** @var string */
    public $name;

    /** @var array */
    public $options;

    /** @var string */
    private $selected;

    public function __construct(string $name, array $options, string $selected = null)
    {
        $this->name = $name;

        $this->options = $options;

        $this->selected = old($name, $selected);
    }

    public function isSelected(string $optionName): bool
    {
        return $optionName === $this->selected;
    }
}
```

Notice that this class extends `\Spatie\BladeX\ViewModel`. Every attribute on the `select-field` will be passed to its constructor. This happens based on the attribute names: the `name` attribute will be passed to the `$name` constructor argument, the `options` attribute will be passed to the `$options` argument and so on. Any other argument will be resolved out of Laravel's [IoC container](https://laravel.com/docs/5.6/container), so you can inject external dependencies.

All public properties and methods on the view model will be passed to the Blade view that will render the `select-field` component. Public methods will be available in as a closure stored in the variable that is named after the public method in view model. This is what that view looks like.

```

    @foreach($options as $value => $label)
        {{ $label }}
    @endforeach

```

When rendering the BladeX component, this is the output:

```

        Belgium
        France
        The Netherlands

```
