Comment intégrer un système d’onglets
Prérequis
Afin de pouvoir suivre ce guide, il faut préalablement avoir intégré un composant AP4.
Introduction
On se propose ici de mettre en place un système d’onglets pour chaque section. Le premier onglet comportera la grille créée précédemment. Un clic sur le rang de la grille ouvrira le Smart Element correspondant dans un nouvel onglet, en mode consultation. Un clic sur le boutton d’ajout d’un onglet ouvrira un formulaire de création du Smart Element.
Recommandation
Pour vous familiariser avec l’utilisation du système d’onglets proposé par Anakeen Platform 4, il est fortement recommandé de consulter la documentation associée disponible ici.
Comment configurer le store de notre application
Afin de garder un état persistent des onglets par section dans notre application, nous utiliserons le store Vue
directement inclus dans Nuxt.js
Recommandation
Si vous n’êtes pas familier avec le concept de Vuex
et de store
, il est fortement recommandé de lire la
documentation associée disponible ici.
Il est également recommandé de consulter la documentation d’utilisation du store
avec Nuxt.js
disponible ici.
Créer le répertoire store
à la racine :
mkdir store
Créer les fichiers store/boisson.js
, store/menu.js
et store/plat.js
avec le contenu identique suivant :
touch store/boisson.js store/menu.js store/plat.js
export const state = () => ({
tabs: [],
});
export const mutations = {
pushTab(state, tab) {
state.tabs.push(tab);
},
removeTab(state, tabId) {
state.tabs = state.tabs.filter((tab) => tab.tabId !== tabId);
},
};
export const getters = {
getTabs: (state) => state.tabs,
};
l’arborescence du répertoire store est alors :
store
├── boisson.js
├── menu.js
└── plat.js
Comment configurer les onglets Anakeen Platform 4
Recommandation
Dans l’exemple suivant, nous utiliserons le routeur Vue
intégré à Nuxt.js
. Si vous n’êtes pas familier avec ces
concepts, il est fortement recommandé de lire la documentation associée
disponible ici.
Modifier le fichier le composant de section components/RestauratecSection.vue
:
<template>
<div class="restauratec-section">
<ank-tabs
v-model="selectedTab"
ref="ankTabs"
@tabRemove="onTabRemove"
@tabClick="onTabClick"
@tabAdd="onTabAdd"
:addable="!isCreationTabOpened"
>
<ank-tab tabId="grid" label="Smart Elements">
<div class="restauratec-grid">
<ank-se-grid
:collection="gridConfig.collection"
:columns="gridConfig.columns"
:actions="gridActions"
@rowActionClick="onRowActionClick"
/>
</div>
</ank-tab>
<ank-smart-tab
v-for="(tab, index) in tabs"
:identifier="tab.initid"
:tabId="tab.tabId"
:key="tab.tabId"
:viewId="tab.viewId"
closable
/>
</ank-tabs>
</div>
</template>
<script>
import Vue from "vue";
import AnkTabs from "@anakeen/user-interfaces/components/lib/AnkTabs.esm";
import AnkSmartTab from "@anakeen/user-interfaces/components/lib/AnkSmartElementTab.esm";
import AnkTab from "@anakeen/user-interfaces/components/lib/AnkTab.esm";
import AnkSmartElementGrid from "@anakeen/user-interfaces/components/lib/AnkSmartElementGrid.esm";
import setup from "@anakeen/user-interfaces/components/lib/setup.esm";
Vue.use(setup);
export default {
components: {
"ank-se-grid": () =>
new Promise((resolve) => {
Vue.$_globalI18n.recordCatalog().then(() => {
resolve(AnkSmartElementGrid);
});
}),
AnkTabs,
AnkSmartTab: () => AnkSmartTab,
AnkTab,
},
props: ["section", "gridConfig"],
data() {
return {
gridActions: [
{
action: "display",
title: "Afficher",
iconClass: "fa fa-eye",
},
],
};
},
computed: {
selectedTab: {
get: function () {
return this.$route.params.tab ? this.$route.params.tab : "grid";
},
set(tab) {
this.$router.push(`/${this.section}/${tab}`);
},
},
tabs() {
return this.$store.getters[`${this.section}/getTabs`];
},
isCreationTabOpened() {
return this.tabs.filter((tab) => tab.tabId === "creation").length > 0;
},
},
methods: {
onRowActionClick(e) {
if (e.data.type === "display") {
e.preventDefault();
const initid = e.data.row.properties.initid.toString();
const tab = {
initid,
tabId: initid,
viewId: "!defaultConsultation",
};
this.addTab(tab);
this.selectTab(tab.tabId);
}
},
addTab(tab) {
this.$store.commit(`${this.section}/pushTab`, tab);
},
onTabRemove(tabId) {
this.removeTab(tabId);
const nextTabId = this.tabs.length ? this.tabs[this.tabs.length - 1].tabId : "grid";
this.selectTab(nextTabId);
},
removeTab(tabId) {
this.$store.commit(`${this.section}/removeTab`, tabId);
},
onTabClick(e) {
this.selectTab(e.tabId);
},
selectTab(tabId) {
this.selectedTab = tabId;
},
onTabAdd() {
const tab = {
initid: this.gridConfig.collection,
tabId: "creation",
viewId: "!defaultCreation",
};
this.addTab(tab);
this.selectTab(tab.tabId);
},
},
};
</script>
<style lang="scss">
.restauratec-section {
display: flex;
flex-direction: column;
align-items: center;
.ank-tabs {
width: 100%;
.ank-tab-pane {
display: flex;
flex-direction: column;
align-items: center;
.restauratec-grid {
height: 39rem;
width: 80%;
margin-top: 5rem;
border: 1px solid;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
}
}
}
</style>
Recommandation
Nous allons utiliser le système de routes dynamiques de Nuxt.js
. Si vous n’êtes pas familier avec ces concept, il est
fortement recommandé de lire la documentation associée
disponible ici.
Déplacer le fichier /pages/Boisson.vue
vers /pages/boisson/_tab.vue
:
mkdir pages/boisson && mv pages/Boisson.vue pages/boisson/_tab.vue
Faire de même avec Plat
et Menu
:
mkdir pages/plat && mv pages/Plat.vue pages/plat/_tab.vue
mkdir pages/menu && mv pages/Menu.vue pages/menu/_tab.vue
Modifier le contenu de chaque fichier _tab.vue
:
pages/boisson/_tab.vue
:
<template>
<div class="restauratec-boisson-wrapper">
<restauratec-section :gridConfig="gridConfig" :section="section" />
</div>
</template>
<script>
import RestauratecSection from "../../components/RestauratecSection";
export default {
components: { RestauratecSection },
key(route) {
return route.name;
},
data() {
return {
gridConfig: {
collection: "BOISSON",
columns: [
{ field: "consommable_title" },
{ field: "consommable_creator" },
{ field: "consommable_price_incl_vat" },
],
},
section: "boisson",
};
},
};
</script>
pages/menu/_tab.vue
:
<template>
<div class="restauratec-menu-wrapper">
<restauratec-section :gridConfig="gridConfig" :section="section" />
</div>
</template>
<script>
import RestauratecSection from "../../components/RestauratecSection";
export default {
components: { RestauratecSection },
key(route) {
return route.name;
},
data() {
return {
gridConfig: {
collection: "MENU",
columns: [{ field: "menu_title" }, { field: "menu_price" }],
},
section: "menu",
};
},
};
</script>
pages/plat/_tab.vue
:
<template>
<div class="restauratec-plat-wrapper">
<restauratec-section :gridConfig="gridConfig" :section="section" />
</div>
</template>
<script>
import RestauratecSection from "../../components/RestauratecSection";
export default {
components: { RestauratecSection },
key(route) {
return route.name;
},
data() {
return {
gridConfig: {
collection: "PLAT",
columns: [{ field: "consommable_title" }, { field: "consommable_creator" }, { field: "plat_type" }],
},
section: "plat",
};
},
};
</script>
L’arborescence finale du répertoire pages
est alors :
pages
├── boisson
│ └── _tab.vue
├── index.vue
├── menu
│ └── _tab.vue
└── plat
└── _tab.vue
Tester nos modifications
Lancez le serveur Anakeen Platform 4 :
make env-start
Puis lancez le serveur de développement :
npm run dev
Vous pouvez voir les onglets sous chaque section, par exemple http://localhost:3000/plat
: