Creating Views in Laravel 5.1

Access all tutorials in sprocket icon.

August 18, 2015 from author Bill Keck.

Creating Views in Laravel 5.1

Please note that this tutorial builds on previously tutorials, which, if you want to follow along exactly, you should read first:

Also note that your actual workflow may differ from the tutorials, it is not necessary to adopt a workflow that creates a model first for example. I only did it this way to make it easy for me to demonstrate. Different developers have their own approaches, so you will have to determine that for yourself.

So from our Restful Controller Tutorial, we have a WidgetController with 8 methods:

  • index
  • create
  • store
  • show
  • edit
  • update
  • destroy
  • search

I added the 8th method, search, so that is not a standard method that you get when you create a controller using artisan. Of the methods that come out-of-the-box, the following would have corresponding views:

  • index
  • show
  • create
  • edit

The destroy method is more of an action, it doesn’t require a dedicated view, so it is not on the list.

Typically, an index view is used to show a list of results. The show view is often used to show the details of an individual record. The create method typically shows a form for creating a new record, and edit shows a form for updating a specific record.

Now if you are building an application with multiple models, as most applications will have, then you need to create a folder within the views folder with the name of the model you are building views for. In our case, this will be the widget folder, so go ahead and create that now.

If we didn’t have a folder for our views within the views folder, we would only be able to use the filename index once, which is not what we want. Obviously, we are following a pattern, and we want to be able to use this pattern for all models.

You probably know by now that views use the blade template engine. Blade is a fantastic templating engine that provides us with easy to use syntax, allowing us to mix php and html much more easily than we could without it. We will see this in action in a minute.

Another benefit to Blade is that it compiles the files into standard PHP, so you don’t incur server overhead by using it. This is just awesome.

The Blade file names follow this convention:



index.blade.php
show.blade.php

Anyway, you get the idea. Without further ado, create a widget folder in the views folder. Then you need to create an index.blade.php file within that folder. Then change the index.blade.php file to:



@extends('layouts.master')

@section('title')

    <title>The Widget Page </title>

   @endsection

@section('content')

   {!! Breadcrumb::withLinks(['Home' => '/', 'Widgets' => '/widget']) !!}

   @include('widget.noresults')

    <br>

   @include('widget.searchform')

   @if(isset($results))

       @include('widget.searchresults')

       @else

       @include('widget.allrecords')

       @endif

@endsection

@section('scripts')
    <script>

       function ConfirmDelete()
       {
           var x = confirm("Are you sure you want to delete?");
           if (x)
               return true;
           else
               return false;
       }

    </script>

@endsection

Let’s just knock this down one line at a time. We start with:



@extends('layouts.master')

The @extends allows us to inject the pieces of our view into a master page. In this case, we are telling it we want to extend layouts.master. The layouts folder is inside the views folder if you have followed the tutorial on creating a Master page. And the actual master page is master.blade.php.

For more information on creating a Master page, please see my tutorial on Master pages.

Next we add an @section tag, which let’s us insert a section into the Master page:



@section('title')

    <title>The Widget Page </title>

   @endsection

So in the Master page, there is an @yield(‘title) tag, and this is where this section is injected. In this case, we want the <title> </title> for this page.

Next we have an opening @section(‘content’) tag. Everything that falls between @section(‘content’) and @endsection(‘content’) will be injected into @yield(‘content’) in the master page.

After the opening @section(‘content’), we have:



   {!! Breadcrumb::withLinks(['Home' => '/', 'Widgets' => '/widget']) !!}

If you have the Laravel Bootstrapper package installed, this prints a beautiful Bootstrap breadcrumb to the view. If you don’t have it, you can get the installation instructions from my top 10 Laravel packages tutorial. If you don’t want to use it, just chop it out.

Next we have:



  @include('widget.noresults')

    <br>

Here we are including a view partial. This include statement is calling noresults.blade.php inside of the widget folder, which is inside the view folder.

Since that doesn’t exist, let’s create it now. Place the following in noresults.blade.php:



 @if (Session::has('noResults'))

    <div class="alert alert-error" role"alert">{{ Session::get('noResults') }} </div>

   {{  session()->forget('noResults') }}

@endif

Ok, this walks us right into a control structure using Blade. Referencing the WidgetController index method:



public function index()
{

  $widgets = Widget::paginate(10);

   $count =  DB::table('widgets')->count();

  if (session()->has('message')){

      Session::flash('noResults', 'Sorry, we found 0 results');
   }

   return view('widget.index', compact('widgets', 'count'));
}

You can see we are passing noResults via session. The point is that if noResults is present in the session, we show an alert:



  <div class="alert alert-error" role"alert">{{ Session::get('noResults') }} </div>

That is Bootstrap alert with Blade syntax echoing the Session value of ‘noResults.’ Everything between the {{ }} is an echo statement for php. You can see how clean and readable that is.

When you need to echo without escaping html, use {!! !!}. We will see an example of that soon.

The last thing we do in the if statement is unset the session:



{{  session()->forget('noResults') }}

The purpose of the noresults.blade.php view partial is to produce the ‘Sorry, we found 0 results’ message when there are no results from a search query.

Just to keep it clear, let’s look at the partial again:



 @if (Session::has('noResults'))

    <div class="alert alert-error" role"alert">{{ Session::get('noResults') }} </div>

   {{  session()->forget('noResults') }}

@endif

The reason why we extracted this is to keep our code in index.blade.php as clean as possible. It also allows for reuse of code. If we had several models that used a session to return a no results message, we could put the view partial in a folder named partials, then reuse it for multiple views. This cuts down on code duplication and is ultimately much easier to maintain.

Ok, back on index.blade.php, our next line is:



@include('widget.searchform')

So what we have here is a view partial for the search form. Since we don’t have that file yet, let’s go ahead and create searchform.blade.php now:



 <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
    <div class="panel panel-default">
        <div class="panel-heading" role="tab" id="headingOne">
            <h4 class="panel-title">
                <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne">
                    <span class="glyphicon glyphicon-search" aria-hidden="true"> </span> Search
                </a>
            </h4>
        </div>
        <div id="collapseOne" class="panel-collapse collapse " role="tabpanel" aria-labelledby="headingOne">
            <div class="panel-body">
                <h1> Search For a Widget </h1>

                <hr/>

               @include('errors.errors')

                <form class="form-horizontal" role="form" method="POST" action="/widget/search">
                    <input type="hidden" name="_token" value="{{ csrf_token() }}">

                    <div class="form-group">
                        <label class="col-md-4 control-label">Enter Widget Name </label>
                        <div class="col-md-6">
                      <input type="text" class="form-control" name="widget_name" value="" required>
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="col-md-6 col-md-offset-4">
                           <button type="submit" class="btn btn-primary">
                               Search
                            </button>


                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>


 </div>

 <br>

Most of this is straight Bootstrap. I added a glyphicon to the label on the panel. Keep in mind when you see all this put together, that frontend development is not a core strength for me. I’ve tried to keep it as simple as possible.

Please note that in order for this to work, your master page will have to reference Bootstrap’s dependencies. You can check out my Master Page Tutorial for details on that.

So we added the form within the panel-body tag. You can see we are calling a partial errors.errors. If you don’t have that, let’s make the errors folder within the views directory now. Then within that, place the errors.blade.php with the following contents:



@if (count($errors) > 0)
    <div class="alert alert-danger">
        <strong>Whoops! </strong> There were some problems with your input. <br> <br>
        <ul>
           @foreach ($errors->all() as $error)
                <li>{{ $error }} </li>
           @endforeach
        </ul>
    </div>
@endif

So here we have another if statement. The $errors object is always available to the view. So in this case, we are checking if the count is greater than 0, and if so, we display the message and iterate through the errors, using blade’s foreach syntax.

Interspersed php and html can be a real mess. Blade’s intuitive syntax just makes it incredibly easy to read and a pleasure to work with.

Ok, so that’s the errors.errors view partial, which we can use whenever we have a form that can possibly return errors, such as invalid input or empty fields that need to be required.

You can see that we are nesting partials, and just how effective and focused this code is. Separating the code like this makes it way easier to work on and maintain in the long run.

Getting back to the searchform.blade.php partial, we open the form:



  <form class="form-horizontal" role="form" method="POST" action="/widget/search">

In the action, we are listing the url that matches a route that we created for widget/search. Next:



   <input type="hidden" name="_token" value="{{ csrf_token() }}">

You can see that we included csrf_token via the blade syntax:



{{ csrf_token() }}

We only have one input for our form, I kept it simple. Most forms will have more than one field.



 <div class="form-group">
          <label class="col-md-4 control-label">Enter Widget Name </label>
          <div class="col-md-6">
          <input type="text" class="form-control" name="widget_name" value="" required>
          </div>
  </div>

This is Bootstrap form syntax. You can see I added the name of the attribute, widget_name and placed required at the end of the tag. This will force it to have a value before being submitted.

The last thing of note is the submit button:



 <div class="form-group">
        <div class="col-md-6 col-md-offset-4">
        <button type="submit" class="btn btn-primary">
          Search
        </button>

 </div>
 </div

And that’s pretty much all there is to it. You can see again how having this extracted to a view partial keeps view code from being overwhelmed with spaghetti.

Ok, let’s go back to index.blade.php, the next line is:



@if(isset($results))

       @include('widget.searchresults')

       @else

       @include('widget.allrecords')

       @endif

So this is a if statement that checks to see if there are results from a search query. If $results, then we get the widget.searchresults partial, if we don’t have results from a search, we show the widget.allrecords partial instead.

I liked doing it this way because it is so readable and clean. The heavy, messy html has been extracted out to 2 different files. Let’s create searchresults.blade.php with the following:



 <div>
    <div class="panel panel-default">
        <!-- Default panel contents -->
        <div class="panel-heading">{{ $count }} Widgets Found </div>
        <div class="panel-body">
            <a href="/widget/create">
                <button type="button" class="btn btn-lg btn-success">
                   Create New
                </button>
            </a>
        </div>

        <!-- Table -->
        <table class="table">
            <tr>

                <th>Id </th>
                <th>Name </th>
                <th>Edit </th>
                <th>Delete </th>

            </tr>

           @foreach($results as $result )

                <tr>
                    <td>{{ $result->id }}  </td>
                    <td> <a href="/widget/{{ $result->id }}">{{ $result->widget_name }} </a> </td>

                    <td> <a href="/widget/{{ $result->id }}/edit">
                            <button type="button" class="btn btn-default">Edit </button>
                        </a> </td>
                    <td>{!! Form::model($result, ['route' => ['widget.destroy', $result->id],
                       'method' => 'DELETE'
                       ]) !!}
                        <div class="form-group">

                           {!! Form::submit('Delete', array('class'=>'btn btn-danger', 'Onclick' => 'return
                           ConfirmDelete();')) !!}

                        </div>
                       {!! Form::close() !!}
                    </td>
                </tr>
           @endforeach

        </table>

        <div>

        </div>
    </div>
 </div>

This is a basic Bootstrap panel with a table popped inside. You can see in the panel-heading that we echo a $count variable sent from the controller to let us know how many results we have.

Then we have a create button:



 <a href="/widget/create">
                <button type="button" class="btn btn-lg btn-success">
                   Create New
                </button>
            </a>

This route has already been provided by the Route Resource from our previous Route Resource tutorial.

Next we get the table heading:



 <!-- Table -->
        <table class="table">
            <tr>

                <th>Id </th>
                <th>Name </th>
                <th>Edit </th>
                <th>Delete </th>

            </tr>

You can see we are going to have an id column, a name column, an edit column, and a delete column.

Next we have the main part of the table:



@foreach($results as $result )

                <tr>
                    <td>{{ $result->id }}  </td>
                    <td> <a href="/widget/{{ $result->id }}">{{ $result->widget_name }} </a> </td>

                    <td> <a href="/widget/{{ $result->id }}/edit">
                            <button type="button" class="btn btn-default">Edit </button>
                        </a> </td>
                    <td>{!! Form::model($result, ['route' => ['widget.destroy', $result->id],
                       'method' => 'DELETE'
                       ]) !!}
                        <div class="form-group">

                           {!! Form::submit('Delete', array('class'=>'btn btn-danger', 'Onclick' => 'return
                           ConfirmDelete();')) !!}

                        </div>
                       {!! Form::close() !!}
                    </td>
                </tr>
           @endforeach

        </table>

Obviously, each pass of the foreach loop creates the table rows. You can see the Blade syntax in the td tags. For the delete button, we actually have a form because for security purposes, delete has to come via post, not a get request.

Also note, the @foreach loop is using the $results object that is returned from our search method in the WidgetController.

So that is the interesting part of that view partial.

Next we go back to index.blade.php to the call to include allresults.blade.php. Since we have not made that partial, let’s do that now. Create allresults.blade.php with the following:



 <div>
    <div class="panel panel-default">
        <!-- Default panel contents -->
        <div class="panel-heading">{{ $count }} Widgets </div>
        <div class="panel-body">
            <a href="/widget/create"> <button type="button" class="btn btn-lg btn-success">
                   Create New </button> </a>
        </div>

        <!-- Table -->
        <table class="table">
            <tr>

                <th>Id </th>
                <th>Name </th>
                <th>Edit </th>
                <th>Delete </th>

            </tr>
           @foreach($widgets as $widget )

                <tr>
                    <td>{{ $widget->id }}  </td>
                    <td> <a href="/widget/{{ $widget->id }}">{{ $widget->widget_name }} </a> </td>

                    <td>  <a href="/widget/{{ $widget->id }}/edit">
                            <button type="button" class="btn btn-default">Edit </button> </a> </td>
                    <td>{!! Form::model($widget, ['route' => ['widget.destroy', $widget->id],
                       'method' => 'DELETE'
                       ]) !!}
                        <div class="form-group">

                           {!! Form::submit('Delete', array('class'=>'btn btn-danger', 'Onclick' => 'return ConfirmDelete();')) !!}

                        </div>
                       {!! Form::close() !!} </td>
                </tr>
           @endforeach
        </table>
        <div>

           {!! $widgets->render() !!}

        </div>
    </div>
 </div>

This is very similar to the searchresults partial, except we are using a $widgets object instead of $results. The other difference is that we include:



  {!! $widgets->render() !!}

This for the pagination method that returns the results in groups of 10 records per page. Since we now have the allresults.blade.php separated out as a partial, we can refine it how we wish.

Ok, let’s go back to index.blade.php. For easy reference, let’s look at the content section:



@section('content')

   {!! Breadcrumb::withLinks(['Home' => '/', 'Widgets' => '/widget']) !!}

   @include('widget.noresults')

    <br>

   @include('widget.searchform')

   @if(isset($results))

       @include('widget.searchresults')

       @else

       @include('widget.allrecords')

       @endif

@endsection

Ok, we wrap it up by using the @endif tag and then the @endsection tag.

The last part of index.blade.php is a little piece of javascript that we use to put an alert on the delete button, so that users don’t accidentally delete records by clicking the button:



@section('scripts')
    <script>

       function ConfirmDelete()
       {
           var x = confirm("Are you sure you want to delete?");
           if (x)
               return true;
           else
               return false;
       }

    </script>

@endsection

You can see we are using the scripts section, which will get injected into @yield(‘scripts’) in the Master page. You don’t have to put the actual script in here, it could easily be a call to public/js folder, if that is the name and path of where you keep your javascript files.

Anyway, that wraps up our index.blade.php and related view partials. All we have left is create.blade.php, show.blade.php, and edit.blade.php.

Let’s start with create.blade.php:



@extends('layouts.master')

@section('title')
    <title>Create a Widget </title>
   @endsection

   @section('content')

       {!! Breadcrumb::withLinks(['Home' => '/', 'Widgets' => '/widget', 'Create']) !!}

        <h1>Create a New Widget </h1>


        <hr/>

       @include('errors.errors')


       {!! Form::open(array('url' => '/widget', 'class' => 'form')) !!}

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

        <div class="form-group">

           {!! Form::submit('Create Widget', array('class'=>'btn btn-primary')) !!}

        </div>

       {!! Form::close() !!}



       @endsection

So this is a very simple form with one input. We are using Bootstrapper’s form helper to open the form:



{!! Form::open(array('url' => '/widget', 'class' => 'form')) !!}

Note that we’re using the {!! !!} which doesn’t escape HTML because we want it to print the form html. It’s all incredibly easy to understand.

Next is the edit.blade.php file, which we need to make now:



@extends('layouts.master')

@section('title')
    <title>Edit a Widget </title>
   @endsection

   @section('content')

       {!! Breadcrumb::withLinks(['Home' => '/', 'Widgets' => '/widget', $widget->widget_name]) !!}

        <h1>Update {{ $widget->widget_name }} </h1>


        <hr/>

       @include('errors.errors')


       {!! Form::model($widget, ['route' => ['widget.update', $widget->id],
       'method' => 'PATCH',
       'class' => 'form',
       ]) !!}

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

        <div class="form-group">

           {!! Form::submit('Update Widget', array('class'=>'btn btn-primary')) !!}

        </div>

       {!! Form::close() !!}

       @endsection

This is almost the same as the create.blade.php partial, but we use the Bootstrapper form helper to do a form model binding:



{!! Form::model($widget, ['route' => ['widget.update', $widget->id],
       'method' => 'PATCH',
       'class' => 'form',
       ]) !!}

So this will put the old value of widget_name in the form for reference. Also note, the method is set to PATCH, which is not supported by HTML, but Laravel makes the conversion for us.

The first parameter of the model method is the model, in this case $widget. Then we get the route, along with the model id, in this case $widget->id.

And now to finish up our Views tutorial, we will create the show view:



@extends('layouts.master')

@section('title')
    <title>{{ $widget->widget_name }} </title>
   @endsection

@section('content')
   {!! Breadcrumb::withLinks(['Home' => '/', 'Widgets' => '/widget', $widget->widget_name => $widget->id]) !!}
    <br>
    <div>
        <div class="panel panel-default">
            <!-- Default panel contents -->
            <div class="panel-heading">{{ $widget->widget_name }} Widget </div>
            <div class="panel-body">
                <a href="/widget/create"> <button type="button" class="btn btn-lg btn-success">
                       Create New </button> </a>
            </div>

            <!-- Table -->
            <table class="table">
                <tr>

                    <th>Id </th>
                    <th>Name </th>
                    <th>Edit </th>
                    <th>Delete </th>

                </tr>


                    <tr>
                        <td>{{ $widget->id }}  </td>
                        <td>{{ $widget->widget_name }} </td>

                        <td>  <a href="/widget/{{ $widget->id }}/edit">
                                <button type="button" class="btn btn-default">Edit </button> </a> </td>
                        <td>{!! Form::model($widget, ['route' => ['widget.destroy', $widget->id],
                           'method' => 'DELETE'
                           ]) !!}
                            <div class="form-group">

                               {!! Form::submit('Delete', array('class'=>'btn btn-danger', 'Onclick' => 'return ConfirmDelete();')) !!}

                            </div>
                           {!! Form::close() !!} </td>
                    </tr>

            </table>

        </div>
    </div>

@endsection
@section('scripts')
    <script>

       function ConfirmDelete()
       {
           var x = confirm("Are you sure you want to delete?");
           if (x)
               return true;
           else
               return false;
       }

    </script>

@endsection

You can see that we are again using the small piece of javascript as an alert. You should probably extract that out to separate file to avoid duplication. I will leave that for you to implement.

This is pretty much like our allresults.blade.php file, except we don’t have a foreach loop because there is only going to be one row of results.

The $widget object holds the correct model instance from the show method in the WidgetController.

I hope you have enjoyed this tutorial and found it useful. Click on the sprocket icon at the top of the page to see all tutorials.

Please comment, share, and like if you can, thanks!

I don’t have a donate button, but If you would like to support my work, you can do so by buying one of my 99¢ books, I really appreciate it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s