---
# System prepended metadata

title: VueJS Workshop - Session 1 devoir pour session 2 (06.11.2020)

---

# VueJS Workshop - Session 1 devoir pour session 2 (06.11.2020)

Voici les devoir à faire pour la prochaine fois. Vous devez faire les chapitre 6 et 7 au minimum et 8 pour ceux qui veulent prendre un peu d'avance.

La prochaine fois je vais récap se qu'on avait vu à la session 1 et récap ces devoirs, mais je ne vais pas tout refaire dans le détail.

Donc si vous souhaitez tout comprendre je vous conseille de lire ce petit document.

Il parait long, mais il y a beaucoup d'exemple de code et tous est expliqué.

Je répondrais à vos questions la prochaine fois si il y en a.

Merci d'avance et à Vendredi :)

# 6. Event Handeling

Nous allons maintenant voir comment gérer les événements avec Vue grâce à la directive `v-on`.

## Exemple simple

Faisons un exemple en ajoutant un système de panier à notre site.

Commençons par ajouter un bouton permettant d'ajouter des éléments dans notre panier.

Il faut ajouter une var `cart` dans data qui contiendra la valeur actuelle de notre panier.
Puis ajouter un bouton dans l'html en y ajoutant la directive `v-on` et en incrémentant le panier de 1 à chaque clique.
```html
<button v-on:click="cart += 1">
  Ajouter au panier
</button>
```
> Il existe une syntaxe plus courte pour `v-on`, il s'agit du `@` donc par exemple `v-on:click` donnera `@click`

Ici nous avons effectué l'opération directement dans l'html car notre opération est simple. Dans le cas ou nous souhaitons effectué plusieurs actions il est largement préférable d'utiliser des méthodes. Cela tombe bien car Vue permet de faire cela.

## methods

Pour se faire ajoutons l'élément `methods` à notre app Vue dans notre code JS au même niveau que data.

```js
data() {
},
methods: {
  method1: function() {
  },
  method2: function() {
  }
}
```

Il est maintenant possible d'ajouter une nouvelle méthode afin de pouvoir ensuite l'utiliser dans l'html.

```js
methods: {
  addToCart: function() {
    this.cart += 1
  },
```

> `this.cart` fait référence à la var `cart` dans data
> Les méthodes peuvent également être écrite comme ceci : `addToCart: function() {}` --> `addToCart() {}`

## Carrousel

Ce qui pourrait être vraiment sympa c'est de faire un carrousel pour montrer plusieurs images du café à l'utilisateur.

Nous allons utiliser le tableau d'objet que nous avons créé précédemment `carouelImages`. Il faut ajouter un attribut `image` à chaque objet qui contiendra le lien vers une image dans notre dossier images.

```js
carouselImages: [
  {
    id: 1,
    text: 'Capsule 1',
    image: './images/colombia.png',
  },
  {
    id:  2,
    text: 'Capsule 2',
    image: './images/colombia_de_cote.png',
  },
  {
    id: 3,
    text: 'Tasse',
    image: './images/colombia_tasse.png',
  },
  {
    id: 4,
    text: 'Paquet',
    image: './images/colombia_paquet.png',
  }
],
```

Ensuite nous pouvons modifier notre html comme ceci afin d'afficher une image en dessous de l'image principale. Il ne nous reste plus qu'à ajouter la directive `@mouseover` et la relier à une méthode `updateImage` dans data qui va changer la valeur de la var `image`

```html
<div>
  <span v-for="carouselImage in carouselImages"
    :key="carouselImage.id"
    @mouseover="updateImage(carouselImage.image)">
    <img height="50"
      alt="carouselImage.text"
      :src="carouselImage.image">
  </span>
</div>
```

Il est possible d'utiliser d'autre événement comme `change` sur des radios p. ex.

## Challenge

Créer un nouveau bouton et une nouvelle méthode pour décrémenter le nombre d'objet dans le panier.

# 7. Class & Style Binding

Nous allons voir comment Vue permet d'effectuer des actions sur les styles et les classes.

## :style

Changeons la couleur des détails du café.

Il faut commencer par adapter le tableau `details` dans data pour répondre à nos nouveaux besoin et profitons-en pour lui donner un attribut id.

```js
details: [
  {
    id: 1,
    text: 'Doux',
    color: '#6C99C6'
  },
  {
    id: 2,
    text: 'Harmonieux',
    color: '#BF9E74'
  }
],
```

Dans l'html il faut donc adapter son utilisation.
Pour se qui est de clé, ce n'est pas nouveau et il faut également adapter l'utilisation de l'affichage du texte en appelant la propriété de l'objet.
Au niveau du style il suffit d'utiliser `:style` en utilisant l'attribut `color` de `detail` et en le liant à l'attribut css `color`.

```html
<ul>
  <li v-for="detail in details"
    :key="detail.id"
    :style="{ color: detail.color }">
    {{ detail.text }}
  </li>
</ul>
```

## camel vs kebab

Il y a 2 manières possible d'utiliser les attributs css
1. En notation camelCase `:style="{ backgroundColor: detail.color }"` ou
2. En notation 'kebab-case' `:style="{ 'background-color': detail.color }"`

## Objet de style

Il est également possible d'utiliser un objet de style, changeons le style du bouton d'ajout au panier pour illustrer l'exemple :

Dans le JS on crée un objet qui va regrouper tous nos style.
```js
styles: {
  roundButton: {
    borderRadius: "20px",
    padding: "10px",
    backgroundColor: "rgb(0, 114, 180)",
    color: "white",
    cursor: "pointer"
  }
},
```

Dans l'html on ajoute `:style` au bouton. Mais cette fois il suffit d'ajouter notre objet avec un notation bien plus simple car tous les styles sont déjà contenu dans l'objet JS déjà correctement formaté.
```html
<button
  @click="addToCart"
  :style="styles.roundButton">
  Ajouter au panier
</button>
```

## :class

Essayons de voir la différence si on utilise les classes css.

Désactivons les interactions avec notre bouton si le stock est <= 0 en utilisant l'attribut `disabled`.
```html
<button
  @click="addToCart"
  :style="styles.roundButton"
  :disabled="stock <= 0">
  Ajouter au panier
</button>
```

Rendons le tout un peu plus clair visuellement en ajoutant du css. Ne pas oublier `!important` sur nos attributs css, car nous modifions dans une classe le style ajouté depuis l'élément html.
```css
.disabledButton {
  background-color: #d8d8d8 !important;
  cursor: not-allowed !important;
}
```

> Il est possible d'utiliser l'attribut `class` et `:class` sur le même élément html, les classes vont être fusionné

## Opérateur ternaire [ ? : ]

Il est également possible d'effectuer des opérations ternaires. Modifions le style du texte indiquant combien de 
```html
<div :class="[cart > 0 ? 'cartFilled' : '']">
  Panier({{ cart }})
</div>
```

## Challenge

Changer l'opacité de l'image principale à l'aide d'une classe et lorsqu'il n'y à plus de stock.


# 8. Computed Properties

Vue permet de créer des propriétés calculées.

## Cache

Cela présente des avantages, comme le fait que les propriétés calculées sont mises en cachent. Cela veut dire que la propriété est "calculé" une seule fois et ensuite simplement réutilisé (optimisation de la part de Vue), si un élément de cette propriété à changé alors la propriété est calculé à nouveau puis remise en cache.

## Exemple simple avec le titre

Afin de tester cette nouvelle notion nous allons couper le contenu de notre variable `title` en 2 dans data.
```js
order:  'Commander du café',
brand:  'Nespresso',
```

Mais souhaitons continuer d'utiliser la var `title` dans l'html afin de pouvoir utiliser title, order ou brand quand cela est nécessaire.
Nous allons donc créer un propriété calculée et pour se faire il faut ajouter le terme `computed` au même niveau que data et methods dans le JS.
Ensuite nous pouvons créer notre propriété calculée que nous allons nommé `title` afin que son fonctionnement reste identique ou nous l'avions utilisé précédemment.

```js
data() { ... },
methods: { ... },
computed: {
  title() {
    return this.order + ' ' + this.brand
  }
}
```

## Amélioration du carrousel

Maintenant nous allons simplifier et mettre à profit notre apprentissage des propriétés.
Supprimons la var `image = 'url'` dans data et remplaçons la par `selectedImage = 0` qui sera un index pointant sur l'image actuellement sélectionné de notre carrousel.

Ensuite modifions l'appel de la méthode pour mettre cette variable à jour. D'abord dans la boucle for du carrousel ajoutons un index comme ceci `v-for="(carouselImage, index) in carouselImages"`. Puis l'appel à la méthode `@mouseover="updateSelectedImage(index)"` et la méthode dans le JS `updateSelectedImage(index) { this.selectedImage = index }`.
Et pour finir créons une nouvelle propriété calculée afin de remplacer la variable image d'avant `image() { return this.carouselImages[this.selectedImage].image }`.

## Challenge

Remplacer tous les endroits ou nous avons utilisé `stock <= 0` par un propriété calculée. (Attention au condition qui risque de s'inverser dans certain des cas)
