dilusha100 - 2 months ago

I need to allow my users to change/ update their user info ( first name, last name, ... etc) by a front end form ( without accessing to dashboard). So I tried to use {{ forms('user' , $user_id).get() }} command in my twig file. But it is not working. So how to do that?

Answer

finnito - 2 months ago

Hi @dilusha100!

I have solved this very problem but it’s a bit involved! Everything I have done is inside a custom addon.

First you can create some routes to do your profile viewing/editing from your CustomAddonServiceProvider.php

     // Add profile routes
        'profile'                              => [
            'as'   => 'finnito.module.members::profile',
            'uses' => 'Finnito\MembersModule\Http\Controller\Admin\ProfileController@view',
        ],
    'profile/edit'                              => [
            'as'   => 'finnito.module.members::profile.edit',
            'uses' => 'Finnito\MembersModule\Http\Controller\Admin\ProfileController@edit',
        ],

And then I made a ProfileController which extendes AdminController in Http/Controller/Admin:

<?php namespace Finnito\MembersModule\Http\Controller\Admin;

use Anomaly\Streams\Platform\Http\Controller\AdminController;
use Finnito\MembersModule\User\Form\MembersFormBuilder;
use Illuminate\Contracts\Auth\Guard;

class ProfileController extends AdminController {
    public function view(Guard $auth, MembersFormBuilder $form) {
        if(!$user = $auth->user()) {
            abort(404);
        }
        return $this->view->make(
            "finnito.module.members::profile.view",
            compact("user")
        );
    }

    public function edit(Guard $auth, MembersFormBuilder $form) {
        if(!$user = $auth->user()) {
            abort(404);
        }
        // var_dump($user);
        return $form->render($user->id);
    }
}

And then you need to create the MembersFormBuilder.php and MembersFormHandler.php which might look like this:

<?php namespace Finnito\MembersModule\User\Form;

use Anomaly\Streams\Platform\Ui\Form\FormBuilder;
use Anomaly\UsersModule\User\UserModel;
use Illuminate\Http\Request;
use Illuminate\Contracts\Auth\Guard;

class MembersFormBuilder extends FormBuilder {

    protected $model = UserModel::class;

    protected $fields = [
        'first_name' => [
            "type" => "anomaly.field_type.text",
            "placeholder" => "First Name",
        ],
        'last_name' => [
            "type" => "anomaly.field_type.text",
            "placeholder" => "Last Name",
        ],
        'email' => [
            "type" => "anomaly.field_type.text",
            "placeholder" => "Email",
            "required" => true,
        ],
    ];

    protected $options = [
        'redirect' => 'profile',
        "form_view" => "finnito.module.members::profile.edit",
    ];

    protected $sections = [];

    protected $actions = [
        "update" => [
            "text" => "Update",
            "class" => "update",
        ],
    ];
}

And

<?php namespace Finnito\MembersModule\User\Form;

use Illuminate\Routing\Redirector;
use Symfony\Component\HttpFoundation\Response;
use Anomaly\UsersModule\User\UserModel;
use Input;
use Session;
use Request;
use Illuminate\Contracts\Auth\Guard;
use Anomaly\UsersModule\User\UserRepository;
use Finnito\MembersModule\User\Event\UpdatedProfile;

class MembersFormHandler {
    public function handle(
        Guard $auth,
        UserRepository $users,
        MembersFormBuilder $builder,
        Redirector $redirect
    ) {
        if(!$user = $auth->user()) {
            abort(404);
        }
        $values = $builder->getFormValues();
        $u = $users->findByUsername($user->username);
        foreach ($values as $key => $value) {
            $u->$key = $value;
        }
        $users->save($u);
    }
}

And then finally you can create your admin.edit view to render the form! Hah.

{% block content %}
<div class="">
    {{ form.open()|raw }}
    <div class="grid">
        <div class="row">
            <div class="column">
                <h2>Basic Information</h2>
            </div>
        </div>
        <div class="row">
            <div class="column">
                <fieldset>
                {{ form.fields.first_name.input|raw }}
                {{ form.fields.last_name.input|raw }}
                {{ form.fields.email.input|raw }}
                </fieldset>
            </div>
</div>
        <div class="row">
            <div class="column">
                {{ form.actions|raw }}
            </div>
        </div>
    </div>
    {{ form.close()|raw }}
</div>
{% endblock %}

It seems a bit crazy but it works a treat!

finnito - 2 months ago

Hi @dilusha100!

I have solved this very problem but it’s a bit involved! Everything I have done is inside a custom addon.

First you can create some routes to do your profile viewing/editing from your CustomAddonServiceProvider.php

     // Add profile routes
        'profile'                              => [
            'as'   => 'finnito.module.members::profile',
            'uses' => 'Finnito\MembersModule\Http\Controller\Admin\ProfileController@view',
        ],
    'profile/edit'                              => [
            'as'   => 'finnito.module.members::profile.edit',
            'uses' => 'Finnito\MembersModule\Http\Controller\Admin\ProfileController@edit',
        ],

And then I made a ProfileController which extendes AdminController in Http/Controller/Admin:

<?php namespace Finnito\MembersModule\Http\Controller\Admin;

use Anomaly\Streams\Platform\Http\Controller\AdminController;
use Finnito\MembersModule\User\Form\MembersFormBuilder;
use Illuminate\Contracts\Auth\Guard;

class ProfileController extends AdminController {
    public function view(Guard $auth, MembersFormBuilder $form) {
        if(!$user = $auth->user()) {
            abort(404);
        }
        return $this->view->make(
            "finnito.module.members::profile.view",
            compact("user")
        );
    }

    public function edit(Guard $auth, MembersFormBuilder $form) {
        if(!$user = $auth->user()) {
            abort(404);
        }
        // var_dump($user);
        return $form->render($user->id);
    }
}

And then you need to create the MembersFormBuilder.php and MembersFormHandler.php which might look like this:

<?php namespace Finnito\MembersModule\User\Form;

use Anomaly\Streams\Platform\Ui\Form\FormBuilder;
use Anomaly\UsersModule\User\UserModel;
use Illuminate\Http\Request;
use Illuminate\Contracts\Auth\Guard;

class MembersFormBuilder extends FormBuilder {

    protected $model = UserModel::class;

    protected $fields = [
        'first_name' => [
            "type" => "anomaly.field_type.text",
            "placeholder" => "First Name",
        ],
        'last_name' => [
            "type" => "anomaly.field_type.text",
            "placeholder" => "Last Name",
        ],
        'email' => [
            "type" => "anomaly.field_type.text",
            "placeholder" => "Email",
            "required" => true,
        ],
    ];

    protected $options = [
        'redirect' => 'profile',
        "form_view" => "finnito.module.members::profile.edit",
    ];

    protected $sections = [];

    protected $actions = [
        "update" => [
            "text" => "Update",
            "class" => "update",
        ],
    ];
}

And

<?php namespace Finnito\MembersModule\User\Form;

use Illuminate\Routing\Redirector;
use Symfony\Component\HttpFoundation\Response;
use Anomaly\UsersModule\User\UserModel;
use Input;
use Session;
use Request;
use Illuminate\Contracts\Auth\Guard;
use Anomaly\UsersModule\User\UserRepository;
use Finnito\MembersModule\User\Event\UpdatedProfile;

class MembersFormHandler {
    public function handle(
        Guard $auth,
        UserRepository $users,
        MembersFormBuilder $builder,
        Redirector $redirect
    ) {
        if(!$user = $auth->user()) {
            abort(404);
        }
        $values = $builder->getFormValues();
        $u = $users->findByUsername($user->username);
        foreach ($values as $key => $value) {
            $u->$key = $value;
        }
        $users->save($u);
    }
}

And then finally you can create your admin.edit view to render the form! Hah.

{% block content %}
<div class="">
    {{ form.open()|raw }}
    <div class="grid">
        <div class="row">
            <div class="column">
                <h2>Basic Information</h2>
            </div>
        </div>
        <div class="row">
            <div class="column">
                <fieldset>
                {{ form.fields.first_name.input|raw }}
                {{ form.fields.last_name.input|raw }}
                {{ form.fields.email.input|raw }}
                </fieldset>
            </div>
</div>
        <div class="row">
            <div class="column">
                {{ form.actions|raw }}
            </div>
        </div>
    </div>
    {{ form.close()|raw }}
</div>
{% endblock %}

It seems a bit crazy but it works a treat!

dilusha100 - 2 months ago

this seems interesting. I'll try it and give a feedback. thanks

frednwt - 2 months ago

You can do all of this without a custom module. The twig form() is highly customisable.

For example: https://pyrocms.com/help/developer-tools/form-builders/defining-custom-ajax-forms-in-twig

finnito - 2 months ago

I didn't know about this when I figured this out so that is probably a slightly better way to do it, hahah.