X. Vue.js▲
Dans ce chapitre, je vous propose de voir un exemple simple d'utilisation d'un framework JavaScript, en l'occurrence Vue.js, comme gestionnaire côté client associé à Laravel.
Je vous propose de démarrer le projet à partir de celui que j'ai élaboré dans cet article avec Materialize (lien direct de téléchargement). Il y a un lien dans l'article pour vous permettre de télécharger le projet de départ.
Comme exemple je vous propose une simple page qui permet de laisser une pensée pour les utilisateurs enregistrés, donc un simple texte qu'on a envie de partager.
Ce n'est pas une initiation à Vue.js : pour ça, vous pouvez vous référer à mon cours ici . C'est juste pour montrer son utilisation avec Laravel. |
Mettez à jour le fichier .env selon votre configuration. Vous pouvez changer le nom de l'application :
APP_NAME=Pensées
Vous pouvez télécharger le code final de ce chapitre ici . |
D'autre part, j'ai mis en ligne l'application en démonstration ici. Vous pouvez y laisser vos pensées |
X-A. Le serveur▲
X-A-1. Données▲
On va donc créer une table pour mémoriser les pensées :
php artisan make:migration create_pensees_table
Changez ainsi le code de la méthode up :
puis lancez la migration :
php artisan migrate
Si tout s'est bien passé, vous devez avoir ces quatre tables :
On va aussi créer le modèle :
php artisan make:model Pensee
On va également établir les relations. Dans le modèle User on va avoir :
et la réciproque dans le modèle Pensee :
On va aussi penser à l'assignation de masse pour la création d'une pensée dans le modèle Pensee :
protected $fillable
=
[
'
text
'
,
'
user_id
'
,
];
On va un peu remplir nos tables. On commence par créer un factory pour les pensées :
php artisan make:factory PenseeFactory --model
=
Pensee
en complétant le code pour la génération du texte :
2.
3.
4.
5.
6.
7.
8.
9.
<?php
use
Faker\Generator as
Faker;
$factory
->
define(App\Pensee::
class
,
function
(Faker $faker
) {
return
[
'text'
=>
$faker
->
text,
];
}
);
Lancez tinker :
php artisan tinker
On va maintenant créer six utilisateurs avec chacun une pensée :
factory(App\User::
class,
6
)->
create()->
each(function ($u
) {
$u
->
pensees()->
save(factory(App\Pensee::
class)->
make());}
);
Voilà, pour les données on est parés !
X-A-2. Contrôleur▲
On va créer un contrôleur de ressource pour nos pensées :
php artisan make:controller PenseeController --resource
On va ne garder que les méthodes index, create et destroy :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
<?php
namespace
App\Http\Controllers;
use
Illuminate\Http\Request;
class
PenseeController extends
Controller
{
public
function
index()
{
//
}
public
function
store(Request $request
)
{
//
}
public
function
destroy($id
)
{
//
}
}
On va un peu coder tout ça en ajoutant une méthode initiale pour charger l'application :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
<?php
namespace
App\Http\Controllers;
use
Illuminate\Http\Request;
use
App\Pensee;
class
PenseeController extends
Controller
{
public
function
__construct
()
{
$this
->
middleware('auth'
)->
except('app'
,
'index'
);
}
public
function
app()
{
return
view('pensees.index'
);
}
public
function
index(Request $request
)
{
$pensees
=
Pensee::
with('user'
)->
latest()->
get();
$user
=
auth()->
check() ?
auth()->
id() :
0
;
return
response()->
json([
$pensees
,
$user
]
);
}
public
function
store(Request $request
)
{
$request
->
validate([
'text'
=>
'required|max:1000'
,
]
);
$request
->
merge([
'user_id'
=>
$request
->
user()->
id]
);
$pensee
=
Pensee::
create($request
->
all());
return
Pensee::
with('user'
)->
find($pensee
->
id);
}
public
function
destroy(Pensee $pensee
)
{
$this
->
authorize('delete'
,
$pensee
);
$pensee
->
delete();
return
response()->
json();
}
}
En gros, uniquement des choses qu'on a déjà vues dans ce cours…
La méthode merge permet d'ajouter des éléments à la requête. |
X-A-3. Protections▲
On doit protéger les URL qui sont réservées aux utilisateurs authentifiés. On va donc ajouter un constructeur dans le contrôleur pour ajouter le middleware auth pour les méthodes concernées :
2.
3.
4.
public function __construct()
{
$this
->
middleware('
auth
'
)->
except('
app
'
,
'
index
'
);
}
D'autre part, il faut faire en sorte que seul le rédacteur d'une pensée puisse supprimer cette pensée :
php artisan make:policy PenseePolicy --model
=
Pensee
On va garder seulement la méthode delete avec ce code :
Il faut l'enregistrer dans AuthServiceProvider :
Et pour terminer on l'utilise dans le contrôleur :
X-A-4. Routes▲
On a aussi besoin des routes pour accéder aux méthodes du contrôleur qu'on vient de créer et pour un peu réorganiser. Remplacez toutes les routes existantes par celles-ci :
2.
3.
4.
5.
6.
7.
Auth::
routes();
Route::
get('
/
'
,
'
PenseeController@app
'
);
Route::
resource('
pensees
'
,
'
PenseeController
'
,
[
'
only
'
=>
[
'
index
'
,
'
store
'
,
'
destroy
'
,
]]
);
Vous devez donc avoir toutes ces routes :
Notre serveur est maintenant prêt !
X-B. Le client▲
On va donc passer côté client maintenant…
Commencez par générer les modules avec NPM :
npm install
X-B-1. Vue-resource▲
Par défaut, Vue.js n'est pas équipé pour gérer des requêtes HTTP. On va donc installer ce package :
Alors encore une petite commande :
npm install vue-resource
On va déclarer ce composant dans notre fichier resources/assets/js/app.js :
2.
3.
4.
5.
6.
window
.
Vue =
require
(
'vue'
);
var VueResource =
require
(
'vue-resource'
);
Vue.use
(
VueResource);
Vue.
http.
headers.
common[
'X-CSRF-TOKEN'
]
=
document
.
head.querySelector
(
'meta[name="csrf-token"]'
).
content;
La dernière ligne a pour objectif de créer un « header » pour la protection CSRF. Normalement axios devrait le faire, mais pour une raison que j'ignore, ça ne fonctionne pas. |
Maintenant on va pouvoir créer des requêtes HTTP vers notre serveur et recevoir des réponses : en gros, communiquer !
X-B-2. La liste des pensées▲
Par défaut on a un composant nommé Exemple :
On va changer son nom en l'appelant par exemple App :
et donc renseigner en conséquence le fichier resources/assets/js/app.js qui doit donc finalement contenir ce code :
On va avoir besoin d'une vue de départ :
avec ce simple code pour charger le composant de Vue.js :
X-B-2-a. Une liste simple▲
Pour le composant App.vue, on va commencer par ce code :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
<
template>
<
div class
=
"
container
"
>
<
div v-for
=
"
pensee in pensees
"
>
<
h4>
{{
pensee.
user.
name }}
<
/h4
>
<
p>
{{
pensee.
text }}
<
/p
>
<
p>
{{
pensee.
created_at }}
<
/p
>
<
/div
>
<
/div
>
<
/template
>
<script>
export
default {
resource
:
null
,
data
(
) {
return
{
pensees
:
{}
}
},
mounted
(
) {
this
.
resource =
this
.
$resource
(
'
/pensees{/id}
'
)
this
.
resource.get
(
).then
((
response) =>
{
this
.
pensees =
response.
body
}
)
}
}
</
script>
Au niveau des data, une simple variable pensees pour contenir les pensées.
Lorsque le composant est prêt (mounted), on lance la requête GET /pensees et on met le résultat dans pensees.
Dans le template, la directive v-for se charge de générer le HTML.
Si tout se passe bien, vous devez obtenir cet aspect :
X-B-2-b. On améliore l'aspect▲
On va un peu améliorer l'aspect obtenu. On va créer un composant Card :
avec ce code :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
<
template>
<
div class
=
"
card red lighten-2
"
>
<
div class
=
"
card-content white-text
"
>
<
span class
=
"
card-title
"
>
{{
name }}
<
/span
>
<
p>
{{
text }}
<
/p
>
<
p><small>
{{
date }}
<
/small
></p
>
<
/div
>
<
/div
>
<
/template
>
<script>
export
default {
props
:
[
'
name
'
,
'
text
'
,
'
date
'
]
}
</
script>
et on va changer ainsi le code du composant App :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
<
template>
<
div class
=
"
container
"
>
<
div v-for
=
"
pensee in pensees
"
>
<
card :name
=
"
pensee.user.name
"
:text
=
"
pensee.text
"
:date
=
"
pensee.created_at
"
></card
>
<
/div
>
<
/div
>
<
/template
>
<script>
import
Card from
'
./Card
'
export
default {
resource
:
null
,
data
(
) {
return
{
pensees
:
[]
}
},
mounted
(
) {
this
.
resource =
this
.
$resource
(
'
/pensees{/id}
'
)
this
.
resource.get
(
).then
((
response) =>
{
this
.
pensees =
response.
body
}
)
},
components
:
{
Card
}
}
</
script>
Le code est mieux organisé et l'aspect plus présentable :
X-B-2-c. Suppression d'une pensée▲
Maintenant comment faire si un utilisateur veut supprimer une de ses pensées ? Il faudrait prévoir un bouton quelque part qui n’apparaîtrait que pour le rédacteur de la pensée, mais pour le moment, rien ne nous indique que l'utilisateur actuel est le rédacteur de certaines pensées, parce qu'on ne dispose pas de son identifiant…
On va donc modifier la méthode index du contrôleur :
Ainsi, on renvoie les pensées et l'identifiant de l'utilisateur en cours (0 s'il n'y en a pas).
Voici le nouveau composant App :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
<
template>
<
div class
=
"
container
"
>
<
div v-for
=
"
pensee in pensees
"
>
<
card :pensee
=
"
pensee
"
:user
=
"
user
"
@deletePensee
=
"
deletePensee
"
></card
>
<
/div
>
<
/div
>
<
/template
>
<script>
import
Card from
'
./Card
'
export
default {
resource
:
null
,
data
(
) {
return
{
pensees
:
[],
user
:
0
}
},
mounted
(
) {
this
.
resource =
this
.
$resource
(
'
/pensees{/id}
'
)
this
.
resource.get
(
).then
(
response =>
{
this
.
pensees =
response.
body[
0
]
this
.
user =
response.
body[
1
]
}
)
},
components
:
{
Card
},
methods
:
{
deletePensee
(
id) {
this
.
resource.delete
({
id
:
id}
).then
(
response =>
{
let
index =
_.findIndex
(
this
.
pensees,
function
(
o) {
return
o.
id ==
id;
}
)
this
.
pensees.splice
(
index,
1
)
}
)
}
}
}
</
script>
On a le nouveau data user pour mémoriser l'identifiant de l'utilisateur.
On envoie dans le composant Card l'objet pensee et user.
On attend un événement (deletePensee) de la part de Card. Cet événement a pour effet d'activer la méthode deletePensee qui reçoit l'identifiant de la pensée. On envoie alors la requête pour supprimer cette pensée sur le serveur, et au retour on la supprime en local.
Voici le nouveau code pour Card :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
<
template>
<
div class
=
"
card red lighten-2
"
>
<
div class
=
"
card-content white-text
"
>
<
span class
=
"
card-title
"
>
{{
pensee.
user.
name }}
<
/span
>
<
p>
{{
pensee.
text }}
<
/p
>
<
p><small>
{{
pensee.
created_at }}
<
/small
></p
>
<
/div
>
<
div v-if
=
"
deletable
"
class
=
"
card-action
"
>
<
a href
=
"
#
"
@click
.prevent
=
"
deletePensee
"
>
Supprimer cette pensée<
/a
>
<
/div
>
<
/div
>
<
/template
>
<script>
export
default {
props
:
[
'
pensee
'
,
'
user
'
],
computed
:
{
deletable
(
) {
return
this
.
pensee.
user_id ==
this
.
user
}
},
methods
:
{
deletePensee
(
) {
this
.
$emit
(
'
deletePensee
'
,
this
.
pensee.
id)
}
}
}
</
script>
On reçoit maintenant un objet global pensee et aussi user.
On fait apparaître le lien de suppression avec un computed qui teste l'utilisateur.
Pour la suppression, on envoie un événement ($emit
) au parent App.
X-B-2-d. Ajout d'une pensée▲
Il faut aussi pouvoir ajouter une pensée, et donc un formulaire pour la saisie, réservé aux utilisateurs connectés. On va utiliser une fenêtre modale pour le réaliser.
On va ajouter un élément dans le menu et l'activation de la fenêtre modale (resources/views/layouts/app.blade.php). Voici le code complet de la vue résultante :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
<!
DOCTYPE html
>
<
html lang
=
"
{{
app()->
getLocale() }}
"
>
<
head>
<
meta charset
=
"
utf-8
"
>
<
meta http-equiv
=
"
X-UA-Compatible
"
content
=
"
IE=edge
"
>
<
meta name
=
"
viewport
"
content
=
"
width=device-width, initial-scale=1
"
>
<!-- CSRF Token -->
<
meta name
=
"
csrf-token
"
content
=
"
{{
csrf_token() }}
"
>
<
title>
{{
config('app.name'
,
'Laravel'
) }}
<
/title
>
<!-- Styles -->
<
link href
=
"
{{
asset('css/app.css'
) }}
"
rel
=
"
stylesheet
"
>
@yield
('css'
)
<
/head
>
<
body>
<
div id
=
"
app
"
>
@auth
<
ul id
=
"
dropdown1
"
class
=
"
dropdown-content
"
>
<
li>
<
a href
=
"
{{
route('logout'
) }}
"
onclick
=
"
event.preventDefault();
document.getElementById('logout-form').submit();
"
>
Deconnexion
<
/a
>
<
form id
=
"
logout-form
"
action
=
"
{{
route('logout'
) }}
"
method
=
"
POST
"
style
=
"
display: none;
"
>
{{
csrf_field() }}
<
/form
>
<
/li
>
<
li>
<
a class
=
"
modal-trigger
"
href
=
"
#ajout
"
>
Une pensée<
/a
>
<
/li
>
<
/ul
>
@endauth
<
nav>
<
div class
=
"
nav-wrapper
"
>
<
a href
=
"
{{
url('/'
) }}
"
class
=
"
brand-logo
"
>
{{
config('app.name'
,
'Laravel'
) }}
<
/a
>
<
a href
=
"
#
"
data-activates
=
"
mobile-demo
"
class
=
"
button-collapse
"
><i class
=
"
material-icons
"
>
menu<
/i
></a
>
@guest
<
ul class
=
"
right hide-on-med-and-down
"
>
<
li><a href
=
"
{{
route('login'
) }}
"
>
Connexion<
/a
></li
>
<
li><a href
=
"
{{
route('register'
) }}
"
>
Enregistrement<
/a
></li
>
<
/ul
>
<
ul class
=
"
side-nav
"
id
=
"
mobile-demo
"
>
<
li><a href
=
"
{{
route('login'
) }}
"
>
Connexion<
/a
></li
>
<
li><a href
=
"
{{
route('register'
) }}
"
>
Enregistrement<
/a
></li
>
<
/ul
>
@else
<
ul class
=
"
right hide-on-med-and-down
"
>
<
li><a class
=
"
dropdown-button
"
href
=
"
#!
"
data-activates
=
"
dropdown1
"
>
{{
Auth::
user()->
name }}
<
i class
=
"
material-icons right
"
>
arrow_drop_down<
/i
></a
></li
>
<
/ul
>
@endguest
<
/div
>
<
/nav
>
@yield
('content'
)
<
/div
>
<!-- Scripts -->
<script src
=
"
{{
asset('js/app.js'
) }}
"
></
script>
<script>
$(
"
.button-collapse
"
).sideNav
(
)
$(
"
.dropdown-button
"
).dropdown
(
)
$(
'
.modal
'
).modal
(
)
</
script>
<
/body
>
<
/html
>
On ajoute le code de la fenêtre modale dans le composant App, ainsi que sa gestion (mise à jour, validation…) :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
<
template>
<
div class
=
"
container
"
>
<
div v-for
=
"
pensee in pensees
"
:key
=
"
pensee.id
"
>
<
card :pensee
=
"
pensee
"
:user
=
"
user
"
@deletePensee
=
"
deletePensee
"
></card
>
<
/div
>
<
div id
=
"
ajout
"
class
=
"
modal
"
>
<
form v-on:submit.prevent
=
"
addPensee
"
>
<
div class
=
"
modal-content
"
>
<
h4>
Ajout d'une pensée<
/h4
>
<
hr>
<
div class
=
"
input-field col s12
"
>
<
textarea id
=
"
pensee
"
v-model
=
"
texte
"
class
=
"
materialize-textarea
"
></textarea
>
<
label for
=
"
pensee
"
>
Entrez ici votre pensée<
/label
>
<
p class
=
"
red-text
"
>
{{
error
}}
<
/p
>
<
/div
>
<
/div
>
<
div class
=
"
modal-footer
"
>
<
button class
=
"
btn waves-effect waves-light
"
type
=
"
submit
"
>
Envoyer
<
i class
=
"
material-icons right
"
>
send<
/i
>
<
/button
>
<
/div
>
<
/form
>
<
/div
>
<
/div
>
<
/template
>
<script>
import
Card from
'
./Card
'
export
default {
resource
:
null
,
data
(
) {
return
{
error
:
''
,
texte
:
''
,
pensees
:
[],
user
:
0
}
},
mounted
(
) {
this
.
resource =
this
.
$resource
(
'
/pensees{/id}
'
)
this
.
resource.get
(
).then
(
response =>
{
this
.
pensees =
response.
body[
0
]
this
.
user =
response.
body[
1
]
}
)
},
components
:
{
Card
},
methods
:
{
deletePensee
(
id) {
this
.
resource.delete
({
id
:
id}
).then
(
response =>
{
let
index =
_.findIndex
(
this
.
pensees,
function
(
o) {
return
o.
id ==
id;
}
)
this
.
pensees.splice
(
index,
1
)
}
)
},
addPensee
(
) {
this
.
resource.save
({
text
:
this
.
texte }
).then
(
response =>
{
$(
'
#ajout
'
).modal
(
'
close
'
)
this
.
texte =
''
this
.
error =
''
this
.
pensees.unshift
(
response.
body)
},
response =>
{
this
.
error =
response.
body.
errors.
text
[
0
]
}
)
}
}
}
</
script>
et maintenant, on peut ajouter des pensées !
X-B-2-e. Les dates en français▲
Vous avez sans doute remarqué que le format des dates est celui par défaut, lequel n'est pas très adapté au français. On pourrait changer ça au niveau de Laravel, mais on va le faire avec JavaScript.
On va utiliser la superbe librairie moment (l'équivalent de Carbon pour JavaScript) :
npm install moment
et on l'utilise dans le composant Card :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
<
template>
<
div class
=
"
card red lighten-2
"
>
<
div class
=
"
card-content white-text
"
>
<
span class
=
"
card-title
"
>
{{
pensee.
user.
name }}
<
/span
>
<
p>
{{
pensee.
text }}
<
/p
>
<
p><small>
{{
date }}
<
/small
></p
>
<
/div
>
<
div v-if
=
"
deletable
"
class
=
"
card-action
"
>
<
a href
=
"
#
"
@click
.prevent
=
"
deletePensee
"
>
Supprimer cette pensée<
/a
>
<
/div
>
<
/div
>
<
/template
>
<script>
import
moment from
'
moment
'
moment.locale
(
'
fr
'
)
export
default {
props
:
[
'
pensee
'
,
'
user
'
],
computed
:
{
deletable
(
) {
return
this
.
pensee.
user_id ==
this
.
user
},
date
(
) {
return
moment
(
pensee.
created_at).format
(
'
D MMMM YYYY à H:mm:ss
'
)
}
},
methods
:
{
deletePensee
(
) {
this
.
$emit
(
'
deletePensee
'
,
this
.
pensee.
id)
}
}
}
</
script>
On importe la librairie :
On fixe la locale :
moment.locale
(
'fr'
)
On crée un élément calculé :
date
(
) {
return moment
(
pensee.
created_at).format
(
'D MMMM YYYY à H:mm:ss'
)
}
et on l'utilise dans le template :
Maintenant, on a les dates en bon français :
X-B-2-f. La pagination▲
Si on commence à avoir beaucoup de pensées, il va nous falloir une pagination :
npm install vue-paginate
et voilà le code modifié en conséquence pour le composant App :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
<
template>
<
div class
=
"
container
"
>
<
paginate name
=
"
pensees
"
:list
=
"
pensees
"
:per
=
"
3
"
>
<
li v-for
=
"
pensee in paginated('pensees')
"
:key
=
"
pensee.id
"
>
<
card :pensee
=
"
pensee
"
:user
=
"
user
"
@deletePensee
=
"
deletePensee
"
></card
>
<
/li
>
<
/paginate
>
<
paginate-links for
=
"
pensees
"
:classes
=
"
{'ul': 'pagination'}
"
></paginate-links
>
<
div id
=
"
ajout
"
class
=
"
modal
"
>
<
form v-on:submit.prevent
=
"
addPensee
"
>
<
div class
=
"
modal-content
"
>
<
h4>
Ajout d'une pensée<
/h4
>
<
hr>
<
div class
=
"
input-field col s12
"
>
<
textarea id
=
"
pensee
"
v-model
=
"
texte
"
class
=
"
materialize-textarea
"
></textarea
>
<
label for
=
"
pensee
"
>
Entrez ici votre pensée<
/label
>
<
p class
=
"
red-text
"
>
{{
error
}}
<
/p
>
<
/div
>
<
/div
>
<
div class
=
"
modal-footer
"
>
<
button class
=
"
btn waves-effect waves-light
"
type
=
"
submit
"
>
Envoyer
<
i class
=
"
material-icons right
"
>
send<
/i
>
<
/button
>
<
/div
>
<
/form
>
<
/div
>
<
/div
>
<
/template
>
<script>
import
Card from
'
./Card
'
import
VuePaginate from
'
vue-paginate
'
export
default {
resource
:
null
,
data
(
) {
return
{
error
:
''
,
texte
:
''
,
pensees
:
[],
paginate
:
[
'
pensees
'
],
user
:
0
}
},
mounted
(
) {
this
.
resource =
this
.
$resource
(
'
/pensees{/id}
'
)
this
.
resource.get
(
).then
(
response =>
{
this
.
pensees =
response.
body[
0
]
this
.
user =
response.
body[
1
]
}
)
},
components
:
{
Card
},
methods
:
{
deletePensee
(
id) {
this
.
resource.delete
({
id
:
id}
).then
(
response =>
{
let
index =
_.findIndex
(
this
.
pensees,
function
(
o) {
return
o.
id ==
id;
}
)
this
.
pensees.splice
(
index,
1
)
}
)
},
addPensee
(
) {
this
.
resource.save
({
text
:
this
.
texte }
).then
(
response =>
{
$(
'
#ajout
'
).modal
(
'
close
'
)
this
.
texte =
''
this
.
error =
''
this
.
pensees.unshift
(
response.
body)
},
response =>
{
this
.
error =
response.
body.
errors.
text
[
0
]
}
)
}
}
}
</
script>
On a maintenant une pagination :
On pourrait encore améliorer cette application, mais on en restera là…
X-C. En résumé▲
Laravel n'impose rien au niveau de la gestion côté client, et ce ne sont pas les solutions qui manquent. Toutefois, l'installation de Laravel prévoit par défaut une intendance pour Vue.js. On a vu dans ce chapitre que cette intendance est au point et que tout fonctionne de façon efficace. La prise en main de Vue.js est moins difficile que d'autres framework comme « Angular ».
Reste que le choix des outils de gestion côté client n'est pas évident. Souvent, JQuery est amplement suffisant lorsqu'on a juste à générer des requêtes HTTP et à manipuler un peu le DOM. À quel moment devient-il plus intéressant de passer à un framework plus complet ? La réponse n'est pas évidente parce qu’elle dépend de plusieurs facteurs parmi lesquels la maîtrise qu'on a d'un outil particulier n'est pas le moindre.
Si vous n'avez jamais utilisé Vue.js, je vous conseille de l'essayer parce qu'il est simple et puissant et que sa courbe d'apprentissage n'est pas rebutante.