59
votes

Am quite new to Laravel and I have to create a form for create and a form for edit. In my form I have quite some jquery ajax posts. Am wondering whether Laravel does provide for an easy way for me to use the same form for my edit and create without having to add tons of logic in my code. I don't want to check if am in edit or create mode every time when assigning values to fields when the form loads. Any ideas on how I can accomplish this with minimum coding?

13
I wouldn't go that way, separate responsabilities and setup form and controller methods for creation and edition. Laravel offers nice and easy ways to populate the form fields for youJarek Tkaczyk
Check out the documentation about using [Forms and HTML][laravel.com/docs/html], especially the "Opening a new model form"Tim Groeneveld
Additionally, check out this stackoverflow question stackoverflow.com/questions/17510355/…Tim Groeneveld

13 Answers

70
votes

I like to use form model binding so I can easily populate a form's fields with corresponding value, so I follow this approach (using a user model for example):

@if(isset($user))
    {{ Form::model($user, ['route' => ['updateroute', $user->id], 'method' => 'patch']) }}
@else
    {{ Form::open(['route' => 'createroute']) }}
@endif

    {{ Form::text('fieldname1', Input::old('fieldname1')) }}
    {{ Form::text('fieldname2', Input::old('fieldname2')) }}
    {{-- More fields... --}}
    {{ Form::submit('Save', ['name' => 'submit']) }}
{{ Form::close() }}

So, for example, from a controller, I basically use the same form for creating and updating, like:

// To create a new user
public function create()
{
    // Load user/createOrUpdate.blade.php view
    return View::make('user.createOrUpdate');
}

// To update an existing user (load to edit)
public function edit($id)
{
    $user = User::find($id);
    // Load user/createOrUpdate.blade.php view
    return View::make('user.createOrUpdate')->with('user', $user);
}
28
votes

Pretty easy in your controller you do:

public function create()
{
    $user = new User;

    $action = URL::route('user.store');

    return View::('viewname')->with(compact('user', 'action'));
}

public function edit($id)
{
    $user = User::find($id);

    $action = URL::route('user.update', ['id' => $id]);

    return View::('viewname')->with(compact('user', 'action'));
}

And you just have to use this way:

{{ Form::model($user, ['action' => $action]) }}

   {{ Form::input('email') }}
   {{ Form::input('first_name') }}

{{ Form::close() }}
18
votes

For the creation add an empty object to the view.

return view('admin.profiles.create', ['profile' => new Profile()]);

Old function has a second parameter, default value, if you pass there the object's field, the input can be reused.

<input class="input" type="text" name="name" value="{{old('name', $profile->name)}}">

For the form action, you can use the correct endpoint.

<form action="{{ $profile->id == null ? '/admin/profiles' :  '/admin/profiles/' . $profile->id }} " method="POST">

And for the update you have to use PATCH method.

@isset($profile->id)
 {{ method_field('PATCH')}}
@endisset
15
votes

Another clean method with a small controller, two views and a partial view :

UsersController.php

public function create()
{
    return View::('create');
}    

public function edit($id)
{
    $user = User::find($id);
    return View::('edit')->with(compact('user'));
}

create.blade.php

{{ Form::open( array( 'route' => ['users.index'], 'role' => 'form' ) ) }}
    @include('_fields')
{{ Form::close() }}

edit.blade.php

{{ Form::model( $user, ['route' => ['users.update', $user->id], 'method' => 'put', 'role' => 'form'] ) }}
    @include('_fields')
{{ Form::close() }}

_fields.blade.php

{{ Form::text('fieldname1') }}
{{ Form::text('fieldname2') }}
{{ Form::button('Save', ['type' => 'submit']) }}
4
votes

Simple and clean :)

UserController.php

public function create() {
    $user = new User();

    return View::make('user.edit', compact('user'));
}

public function edit($id) {
    $user = User::find($id);

    return View::make('user.edit', compact('user'));
}

edit.blade.php

{{ Form::model($user, ['url' => ['/user', $user->id]]) }}
   {{ Form::text('name') }}
   <button>save</button>
{{ Form::close() }}
2
votes

Instead of creating two methods - one for creating new row and one for updating, you should use findOrNew() method. So:

public function edit(Request $request, $id = 0)
{
    $user = User::findOrNew($id);
    $user->fill($request->all());
    $user->save();
}
2
votes
    Article is a model containing two fields - title and content 
    Create a view as pages/add-update-article.blade.php   

        @if(!isset($article->id))
            <form method = "post" action="add-new-article-record">
            @else
             <form method = "post" action="update-article-record">
            @endif
                {{ csrf_field() }} 

                <div class="form-group">
                    <label for="title">Title</label>            
                    <input type="text" class="form-control" id="title" placeholder="Enter title" name="title" value={{$article->title}}>
                    <span class="text-danger">{{ $errors->first('title') }}</span>
                </div>
                <div class="form-group">
                    <label for="content">Content</label>
                    <textarea class="form-control" rows="5" id="content" name="content">
                    {{$article->content}}

                    </textarea>
                    <span class="text-danger">{{ $errors->first('content') }}</span>
                </div>
                <input type="hidden" name="id" value="{{{ $article->id }}}"> 
                <button type="submit" class="btn btn-default">Submit</button>
            </form>

Route(web.php): Create routes to controller 

        Route::get('/add-new-article', 'ArticlesController@new_article_form');
        Route::post('/add-new-article-record', 'ArticlesController@add_new_article');
        Route::get('/edit-article/{id}', 'ArticlesController@edit_article_form');
        Route::post('/update-article-record', 'ArticlesController@update_article_record');

Create ArticleController.php
       public function new_article_form(Request $request)
    {
        $article = new Articles();
        return view('pages/add-update-article', $article)->with('article', $article);
    }

    public function add_new_article(Request $request)
    {
        $this->validate($request, ['title' => 'required', 'content' => 'required']);
        Articles::create($request->all());
        return redirect('articles');
    }

    public function edit_article_form($id)
    {
        $article = Articles::find($id);
        return view('pages/add-update-article', $article)->with('article', $article);
    }

    public function update_article_record(Request $request)
    {
        $this->validate($request, ['title' => 'required', 'content' => 'required']);
        $article = Articles::find($request->id);
        $article->title = $request->title;
        $article->content = $request->content;
        $article->save();
        return redirect('articles');
    } 
2
votes

For example, your controller, retrive data and put the view

class ClassExampleController extends Controller
{

    public function index()
    {   

        $test = Test::first(1);

        return view('view-form',[
            'field' => $test,
        ]);
    }
}

Add default value in the same form, create and edit, is very simple

<!-- view-form file -->
<form action="{{ 
    isset($field) ? 
    @route('field.updated', $field->id) : 
    @route('field.store')
}}">
    <!-- Input case -->
    <input name="name_input" class="form-control" 
    value="{{ isset($field->name) ? $field->name : '' }}">
</form>

And, you remember add csrf_field, in case a POST method requesting. Therefore, repeat input, and select element, compare each option

<select name="x_select">
@foreach($field as $subfield)

    @if ($subfield == $field->name)
        <option val="i" checked>
    @else
        <option val="i" >
    @endif

@endforeach
</select>
1
votes

In Rails, it has form_for helper, so we could make a function like form_for.

We can make a Form macro, for example in resource/macro/html.php:

(if you don't know how to setup a macro, you can google "laravel 5 Macro")

Form::macro('start', function($record, $resource, $options = array()){
    if ((null === $record || !$record->exists()) ? 1 : 0) {
        $options['route'] = $resource .'.store';
        $options['method'] = 'POST';
        $str = Form::open($options);
    } else {
        $options['route'] = [$resource .'.update', $record->id];
        $options['method'] = 'PUT';
        $str = Form::model($record, $options);
    }
    return $str;
});

The Controller:

public function create()
{
    $category = null;
    return view('admin.category.create', compact('category'));
}

public function edit($id)
{
    $category = Category.find($id);
    return view('admin.category.edit', compact('category'));
}

Then in the view _form.blade.php:

{!! Form::start($category, 'admin.categories', ['class' => 'definewidth m20']) !!}
// here the Form fields
{{!! Form::close() !!}}

Then view create.blade.php:

@include '_form'

Then view edit.blade.php:

@include '_form'
1
votes

You can use form binding and 3 methods in your Controller. Here's what I do

class ActivitiesController extends BaseController {
    public function getAdd() {
        return $this->form();
    }
    public function getEdit($id) {
        return $this->form($id);
    }
    protected function form($id = null) {
        $activity = ! is_null($id) ? Activity::findOrFail($id) : new Activity;

        //
        // Your logic here
        //

        $form = View::make('path.to.form')
            ->with('activity', $activity);

        return $form->render(); 
    }
}

And in my views I have

{{ Form::model($activity, array('url' => "/admin/activities/form/{$activity->id}", 'method' => 'post')) }}
{{ Form::close() }}
0
votes

UserController.php

use View;

public function create()
{
    return View::make('user.manage', compact('user'));
}

public function edit($id)
{
    $user = User::find($id);
    return View::make('user.manage', compact('user'));
}

user.blade.php

@if(isset($user))
    {{ Form::model($user, ['route' => ['user.update', $user->id], 'method' => 'PUT']) }}
@else
    {{ Form::open(['route' => 'user.store', 'method' => 'POST']) }}
@endif

// fields

{{ Form::close() }}
0
votes

I hope this will help you!!

form.blade.php

@php
$name         = $user->name ?? null;
$email        = $user->email ?? null;
$info         = $user->info ?? null;
$role         = $user->role ?? null;
@endphp

<div class="form-group">
        {!! Form::label('name', 'Name') !!}
        {!! Form::text('name', $name, ['class' => 'form-control']) !!}
</div>

<div class="form-group">
        {!! Form::label('email', 'Email') !!}
        {!! Form::email('email', $email, ['class' => 'form-control']) !!}
</div>

<div class="form-group">
        {!! Form::label('role', 'Função') !!}
        {!! Form::text('role', $role, ['class' => 'form-control']) !!}
</div>

<div class="form-group">
        {!! Form::label('info', 'Informações') !!}
        {!! Form::textarea('info', $info, ['class' => 'form-control']) !!}
</div>

<a class="btn btn-danger float-right" href="{{ route('users.index') }}">CANCELAR</a>

create.blade.php

@extends('layouts.app')

@section('title', 'Criar usuário')

@section('content')
        {!! Form::open(['action' => 'UsersController@store', 'method' => 'POST'])  !!}
            @include('users.form')
            <div class="form-group">
                {!! Form::label('password', 'Senha') !!}
                {!! Form::password('password', ['class' => 'form-control']) !!}
            </div>
            <div class="form-group">
                {!! Form::label('password', 'Confirmação de senha') !!}
                {!! Form::password('password_confirmation', ['class' => 'form-control']) !!}
            </div>
            {!! Form::submit('ADICIONAR', array('class' => 'btn btn-primary')) !!}
        {!! Form::close() !!}
@endsection

edit.blade.php

@extends('layouts.app')

@section('title', 'Editar usuário')

@section('content')
        {!! Form::model($user, ['route' => ['users.update', $user->id], 'method' => 'PUT']) !!}
            @include('users.form', compact('user'))
            {!! Form::submit('EDITAR', ['class' => 'btn btn-primary']) !!}
        {!! Form::close() !!}
        <a href="{{route('users.editPassword', $user->id)}}">Editar senha</a>
@endsection

UsersController.php

use App\User;

Class UsersController extends Controller {
  #... 
    public function create()
    {
        return view('users.create';
    }

    public function edit($id)
    {
        $user  = User::findOrFail($id);
        return view('users.edit', compact('user');
    }
}
-1
votes

you can use @$variable in your single blade file for create and edit. it will not through error when variable not defined.

<input name="name" value="@{{$your_variable->name}}">