View Inheritance

A typical webpage has some sections. There may be a navigation bar (or bars) there will probably be a main content section in the middle and there may be a footer with some basic information about the organisation along with some other navigation items such as links to terms and conditions of the companies address.

In that example, typically, the header and the footer will repeat on every webpage in the site. When getting started with HTML, inclusion of these elements typically means copying and pasting them into every section of the website. If those elements change, they must be changed on every page of the website.

View inheritance allows us to pull-in elements which are repeating in different parts of the website from a single file where those elements are stored. The big advantage here is that if they change (which they inevitably will - and often) they need only be changed in one place.

The basic concept of view inheritance allows us to "extend" views the way we would with objects. When you extend a view the view effectively "pulls in" that view from which you are inheriting.

If you don't include the @extends directive in your file then the default layouts.app will be used.

Blade couples the inheritance together with a placeholder model which allows the top level view, in this case layouts.app, to determine where to position the other chunks of HTML relative to the top level template elements. To allow for this Blade uses two other directives which work together - @yield and @section. The @yield directive acts as a place holder and allows the programmer to pass a specific section name which will be picked up from the child view and inserted in that location.

To see a simple example of this in operation we will add a new parent view called layouts.myapp - to do this use the following snippet of code to create a file called myapp.blade.php and place it in the tennisclub/resources/views/layouts folder.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{{ config('app.name') }}</title>
        <meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>

        <!-- Font Awesome -->
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
              integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w=="
              crossorigin="anonymous" referrerpolicy="no-referrer" />

        <!-- Bootstrap 5 -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    </head>

    <body>
        <!-- Bootstrap 5 Navbar -->
        <nav class="navbar navbar-expand-sm bg-dark navbar-dark">
          <div class="container-fluid">
            <ul class="navbar-nav">
              <li class="nav-item">
                <a class="nav-link" href=https://laravel.com/docs>Laravel Documentation</a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href=https://laracasts.com/>Laravel Video Tutorials</a>
              </li>
            </ul>
          </div>
        </nav>
        
        <div id="page-content-wrapper"> 
            <div class="container-fluid"> 
                <div class="row">
                    <!-- Well for left side of the page (to compensate for widescreen) -->
                    <div class="col-lg-2"></div>
                    <!-- Slot for content from Lower Level views with sections called 'content' pulled in here -->
                    <div class="col-lg-8"> @yield('content') </div>
                    <!-- Well for right side of the page (to compensate for widescreen) -->
                    <div class="col-lg-2"></div> 
                </div> 
            </div> 
        </div> 

        <!-- Webpack mix npm generated -->
        <link rel="stylesheet" href="{{asset('css/app.css')}}"> 
        <script src="{{asset('js/app.js')}}"></script>
        @stack('js_scripts')
    </body>
</html>

Next modify your view for new customers from the previous example. Open the file /views/customers/new.blade.php. Add an extends directive at the beginning and wrap the entire form in a @section directive entitled "content" as follows

@extends('layouts.app') 
@section('content') 
    <FORM method="POST" action="/customers/create"> 
        @csrf 
        Enter your first name:<input type="text" name="firstname"><br> 
        Enter your surname:<input type="text" name="surname"><br> 
        <input type="submit"> 
    </FORM> 
@endsection

By wrapping the form in @section('content') @endsection directives and we have named this chunk of HTML allowing Blade to place it into the @yield('content') directive placeholder. This gives us the ability to control how the form is positioned and presented relative to the other HTML elements. In addition, we have introduced a navbar on the parent view. Now anytime we want this navbar to appear on a view we need only add the @extends('layouts.myapp') directive to our view and the navbar will be pulled in.

Next we want to modify the form to include twitter bootstrap styling elements. Change the view in \resources\views\customers\new.blade.php to add the following bootstrap divs and classes.

@extends('layouts.app') 
@section('content')
<FORM method="POST" action="/customers/create"> 
@csrf
    <div class="form-group">
        <label for="firstname">Enter your first name:</label>
        <input type="text" name="firstname" class="form-control"> 
    </div> 
    <div class="form-group">
        <label for="surname">Enter your surname:</label> 
        <input type="text" name="surname" class="form-control"> 
    </div> <input type="submit"> 
</FORM> 
@endsection 

Now your form should look like the following. Twitter bootstrap websites have the advantage of being responsive in nature - meaning they respond to the screen size being used by the user and render a HTML page which will be appropriate for that screen size. The following form will look good whether viewed on a desktop or a phone or anything in between.

Leave a Reply