"Real world" example of CRUD w/ Laravel & Vue (non SPA)

Published 1 year ago by see_kay

"Real world" example of CRUD w/ Laravel & Vue (non SPA)

Hi,

I've been learning Laravel these last few weeks and making progress. Then I started to look into using Vue to offer a better user experience (instant feedback, remote validation etc) but then am stuck for the last few days.

I'm just trying to build a standard business/project management application with the usual projects/messaging/tasks/users-roles-permissions etc. I've integrated Zizaco/Entrust and it works perfectly. I was hoping to find a real world example where laravel is used to render the (blade) view but then Vue is used within for a richer experience within. I did find a lot of SPAs (Vuedo, ) but I'd like to avoid that approach in this case.

At this point, I'm really confused about how to hand off & manage data between laravel and vue for standard operations i.e. project list w/ pagination, CRUD w/ validation etc. How does the controller pass data if it can't be json as the blade view needs to be rendered? How is the data handed off for two way binding (e.g. if I needed to filter the project list)?

I've spent days, and am now more confused than ever! If anyone could point me in the right direction I'd really appreciate it.

Thank you!

Ruffles
Ruffles
1 year ago (294,740 XP)

Build components and use props to pass jsonified data (json_encode($projects)) to the component.

Example:

<projects-list :projects="{{ json_encode($projects) }}"></projects-list>
see_kay

(GitHub-Flavored) Markdown Editor

So I tried a simple example:

  1. blade.php
<customer-list :customers="{{ json_encode($customers) }}"></customer-list>
  1. Customers.vue
<template>
    <table class="table table-hover">
        <thead>
            <tr>
                <th>#</th>
                <th>Name</th>
                <th>Email</th>
                <th>Status</th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="item in customers">
                <td> {{ item.id }} </td>
                <td> {{ item.name }} </td>
                <td> {{ item.email }} </td>
                <td> {{ item.status }}</td>
            </tr>
        </tbody>
    </table>
</template>

<script>
export default {
    props: ['customers'],
    data() {
           return {

           }
    },
}
</script>

and get "Error when rendering component <customer-list>" and "Uncaught TypeError: Cannot read property 'id' of null" errors in the Vue Devtools console

Its probably something really basic I'm missing... And then I'd like to get pagination and column sorting and search in there as well, but that's jumping too far ahead at this point :)

zachleigh
zachleigh
1 year ago (213,150 XP)

What @Ruffles said.

If you want a real world project to look at, I've got a Laravel and Vue package here: https://github.com/zachleigh/larafolio It's not quite finished yet, but it should show you the basic flow of data.

To view the project dashboard, the route hits the DashboardController index method: https://github.com/zachleigh/larafolio/blob/master/src/Http/Controllers/DashboardController.php

public function index()
{
    $projects = Project::all()->sortBy('order')->values();

    $images = $projects->mapWithKeys(function (Project $project) {
        return [$project->name() => $project->getProjectImageUrl()];
    });

    $blocks = $projects->mapWithKeys(function (Project $project) {
        return [$project->name() => $project->getProjectBlockText()];
    });

    return view('larafolio::projects.index', [
        'projects' => $projects,
        'images'   => $images,
        'blocks'   => $blocks,
    ]);
}

Pretty standard. Just building up some data and sending it to a view.

The view is here: https://github.com/zachleigh/larafolio/blob/master/src/resources/views/projects/index.blade.php

<dashboard
    action={{ route('update-portfolio')}}
    :blocks="{{ json_encode($blocks) }}"
    :icons="{{ json_encode([
        'down' => file_get_contents(public_path('vendor/larafolio/zondicons/arrow-thin-down.svg')),
        'up' => file_get_contents(public_path('vendor/larafolio/zondicons/arrow-thin-up.svg')),
        'hidden' => file_get_contents(public_path('vendor/larafolio/zondicons/view-hide.svg')),
        'visible' => file_get_contents(public_path('vendor/larafolio/zondicons/view-show.svg'))
            ]) }}"
    :images="{{ json_encode($images) }}"
    :projects="{{ json_encode($projects) }}"
></dashboard>

In the view, I do some standard stuff and then send the data to the Vue Dashboard component. As @Ruffles showed, I json_encode all objects and arrays.

The Dashboard Vue component is here: https://github.com/zachleigh/larafolio/blob/master/src/resources/assets/js/components/Dashboard.vue It's a bit long so I won't repost the code, but basically I accept the props I passed from the view, set items in the data attribute, and then render another Vue component, ProjectTile, for each project in projects. I use ajax to update data based on user input, as shown in the updateProjectOrder method.

zachleigh
zachleigh
1 year ago (213,150 XP)

@see_kay In the Vue component, set the type when you accept customers:

props: {
    customers: {
        type: Array
    }
}
see_kay

@zachleigh thanks for both your answers. The type: Array worked and now I'm on to figuring out column sorting, pagination & searches :)

I will be reviewing your Dashboard Vue component as well - I think I need to something similar using child components (if I ever get that far)

Many thanks!

Please sign in or create an account to participate in this conversation.