elliotk's avatar

Form for Create and Update - Duplication

Hello,

I have a form for Create and a form for Update/Edit. It seems to me, that most of the logic is the same. Yet I have a lot of repetition of HTML.

The only differences I see are

  1. The Form Action - Create and Update have different URLs
  2. The Value on Form Inputs are populated differently.

Create <input type="text" class="form-control {{ $errors->has('title') ? ' is-invalid' : '' }}" name="title" id="title" value="{{ old('title') }}" placeholder="Title" required>

Update <input type="text" class="form-control {{ $errors->has('title') ? ' is-invalid' : '' }}" name="title" id="title" value="{{ $post->title }}" placeholder="Title" required>

The rest is pretty much the same. Right now, I have 2 files, with 90% the same code, I'd really like to have one file, so it's more maintainable.

I'd be really interested to hear how others handle this.

Thanks

0 likes
4 replies
Talinon's avatar

Laravel Collective along with Blade partials makes this is quite easy.

Make 2 files: create.blade.php & update.blade.php As you stated, the form actions are different, so place the respective form tags into each file. Then, paste all your repetitive markup into a "partial" which both blade files can include.

create.blade.php

{!! Form::open(['url' => 'create', 'method' => 'POST']) !!}
   @include ('_formBody.blade.php')
{!! Form::close() !!}

update.blade.php


// use form model binding to populate the form
{!! Form::model($model, ['method' => 'POST', 'url' => 'update']) !!}
   {{ hidden_field('patch') }}
   @include ('_formBody.blade.php')
{!! Form::close() !!}

_formBody.blade.php

// second parameter as null will default to data bound from model
{!! Form::text('title', null, ['class' => 'form-control', 'placeholder' => 'Title required', 'required']) !!}


// whatever else in your form

You can read more about it here: https://laravelcollective.com/docs/5.4/html#form-model-binding

The other option to include it all in 1 file, would be to run some conditionals..

@if($model->exists)
    <form method="POST" action="create">
@else
    <form method="POST" action="update">
    {{ hidden_field('patch') }}
@endif

<input type="text" class="form-control {{ $errors->has('title') ? ' is-invalid' : '' }}" name="title" id="title" value="{{ old('title', $model->title) }}" placeholder="Title" required>

</form>

elliotk's avatar

I looked at this, wasn't in favour due to the extra overheads. Is there a more simplistic approach?

Talinon's avatar
Talinon
Best Answer
Level 51

I updated my answer above to provide an alternative approach using conditionals and old(), which a lot of developers are gravitating towards.

Using old() is the key.. if old input exists, it'll populate the field with it. If the old input doesn't exist, but the model does, it'll use the model data as the default to populate the field.

old('title', $model->title)

When creating a new resource, within your controller you would want to pass a new model to the view. Otherwise you'll run into errors trying to access properties on an object that doesn't exist. So something like this:

public function create() {
    $model = new App\Model;

    return view('create', compact('model');
}
2 likes

Please or to participate in this conversation.