Ionic + Vuew: strange error when compiling - vue.js

I'm experimenting with vuejs+ionic but when I try to compile on the mac I get this error
TS2339: Property 'selectedDate' does not exist on type '{ handler(date: string): Promise<false | undefined>; deep: boolean; }'.
If I compile in window everything is working.
This is located in the "watch" section.

<template>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-title>Controlli Preoperativi</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Controlli preoperativi</ion-title>
</ion-toolbar>
</ion-header>
<ion-grid>
<ion-row>
<ion-col>
<div class="ion-text-center">
Da qui potrai impostare la presenza o assenza di non conformità nel tuo locale.
<br />
Attenzione, le modifiche nel passato sono possibili solo fino al giorno precedente.
</div>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-item>
<ion-label>imposta la data di lavoro</ion-label>
<ion-datetime display-format="DD/MM/YYYY" v-model="selectedDate"></ion-datetime>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col v-for="item in controlli" :key="item.id">
<ion-card>
<img :src="item.immagine" :alt="item.nome" :title="item.nome" />
<ion-card-header>
<ion-card-title>{{ item.nome }}</ion-card-title>
</ion-card-header>
<ion-card-content>
<div>
{{ item.descrizione }}
</div>
<div>
<ion-item>
<ion-label>presente</ion-label>
<ion-checkbox v-model="item.nonConformitaPresente" :data-id="item.id" data-type="ncp" #click="handleCheckChange(item.id, 'ncp')" />
</ion-item>
</div>
<div>
<ion-item>
<ion-label>non presente</ion-label>
<ion-checkbox v-model="item.nonConformitaNonPresente" :data-id="item.id" data-type="ncnp" #click="handleCheckChange(item.id, 'ncnp')" />
</ion-item>
</div>
<div v-show="item.nonConformitaPresente">
<ion-item>
<ion-label position="floating">problema riscontrato</ion-label>
<ion-textarea rows="5" v-model="item.problemaRiscontrato"></ion-textarea>
</ion-item>
<ion-item>
<ion-label position="floating">risoluzione</ion-label>
<ion-textarea rows="5" v-model="item.risoluzione"></ion-textarea>
</ion-item>
</div>
<div class="ion-text-center" style="margin-top: 15px">
<ion-button type="submit" shape="round" #click="handleSaveButton(item.id)" :data-id="item.id">
Salva
<ion-icon :icon="save"></ion-icon>
</ion-button>
</div>
</ion-card-content>
</ion-card>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import { IonHeader, IonPage, IonDatetime, IonItem, IonIcon, IonButton, alertController, IonTextarea, IonContent, IonCheckbox, IonLabel, IonToolbar, IonTitle, IonCard, IonCardContent, IonCardHeader, IonCardTitle, IonGrid, IonRow, IonCol } from '#ionic/vue';
import { save } from 'ionicons/icons';
import ApiService from '#/services/api.service';
import {ControlloModel} from '#/services/app.service';
export default {
name: 'controlli',
components: { IonHeader, IonPage, IonDatetime, IonItem, IonIcon, IonButton, IonLabel, IonTextarea, IonContent, IonCheckbox, IonToolbar, IonTitle, IonCard, IonCardContent, IonCardHeader, IonCardTitle, IonGrid, IonRow, IonCol },
setup() {
return {
save
}
},
data() {
return {
selectedDate: new Date().toISOString().split('T')[0],
controlli: new Array<ControlloModel>()
}
},
watch: {
selectedDate: {
async handler(date){
const diff = Math.floor(new Date().getTime() - new Date(date).getTime());
const day = 1000 * 60 * 60 * 24;
const days = Math.floor(diff/day);
if(days <0 || days >1){
const alert = await alertController
.create({
cssClass: 'my-custom-class',
header: 'Errore',
subHeader: 'Data non valida',
message: 'La data selezionata non è valida, verrà utlizzato "OGGI" per la visualizzazione dei dati!',
buttons: ['OK'],
});
alert.present();
await alert.onWillDismiss();
date = new Date().toISOString().split('T')[0];
this.selectedDate = date;
return false;
}
await ApiService.get("/api/CheckGiornalieri?data=" + date.substring(0, 10))
.then(response => this.controlli = response.data);
} , deep: true
}
},
created() {
const data = new Date().toISOString().split('T')[0];
ApiService.get("/api/CheckGiornalieri?data=" + data).then(response => this.controlli = response.data);
},
methods: {
handleCheckChange(srcId: string, srcElemType: string){
const currItem = this.controlli.filter(function(elem){ if(elem.id == srcId) return elem; })[0];
if(srcElemType === "ncp"){
currItem.nonConformitaNonPresente = false;
} else {
currItem.nonConformitaPresente = false;
}
},
async handleSaveButton(srcId: string) {
const currItem = this.controlli.filter(function(elem){ if(elem.id == srcId) return elem; })[0];
const response = await ApiService.post("/api/NonConformita",
{
Data : new Date(this.selectedDate),
IdControllo : srcId,
Presente : currItem.nonConformitaPresente,
NonPresente : currItem.nonConformitaNonPresente,
Problema : currItem.problemaRiscontrato,
Risoluzione : currItem.risoluzione
}
);
if(response.data.state === false){
const alert = await alertController
.create({
cssClass: 'my-custom-class',
header: 'Errore',
subHeader: '',
message: response.data.message,
buttons: ['OK'],
});
alert.present();
}
}
}
}
</script>

Related

VueJs - Conditionaly showing elements in table

I have pretty simple table of users here with only 4 cols, and i want to show a button for each user depending on his status 'isActive'. If user is active i want to show button with text 'disable' and vice versa. I am little bit stuck with this because i dont have an idea how can i show these buttons, because i am using vuexy template for this project(admin panel). Is there a way to do this with JSX?
Please take a look at code, i am getting data from mysql with nodejs. Ask me if you need more info. Thanks.
<template>
<div>
<div class="container">
<b-card-text class="mb-2">
<div
v-if="showLoginError"
class="text-center bg-danger colors-container rounded text-white width-360 height-50 d-flex align-items-center justify-content-center mr-1 ml-50 my-1 shadow"
>
<span>{{ loginError }}</span>
</div>
</b-card-text>
<b-card-text class="mb-2">
<div
v-if="showSuccessMessage"
class="text-center bg-success colors-container rounded text-white width-360 height-50 d-flex align-items-center justify-content-center mr-1 ml-50 my-1 shadow"
>
<span>{{ successMessage }}</span>
</div>
</b-card-text>
<section id="card-actions" class="input-section">
<b-row>
<b-col cols="8">
<b-card-actions ref="cardAction">
<validation-observer ref="simpleRules">
<b-form>
<b-row>
<b-col md="6">
<b-form-group>
<validation-provider
#default="{ errors }"
name="First Name"
rules="required"
>
<b-form-input
v-model="name"
:state="errors.length > 0 ? false:null"
placeholder="Twitter username"
/>
</validation-provider>
</b-form-group>
</b-col>
<b-col cols="12">
<b-button
variant="primary"
type="submit"
#click.prevent="validationForm"
>
Submit
</b-button>
</b-col>
</b-row>
</b-form>
</validation-observer>
</b-card-actions>
</b-col>
</b-row>
</section>
// This is table
<b-table responsive="sm" :items="items"/>
</div>
</div>
</template>
<script>
import { ValidationProvider, ValidationObserver } from 'vee-validate'
import {
BFormInput, BFormGroup, BForm, BRow, BCol, BButton, BTable,
} from 'bootstrap-vue'
import { required } from '#validations'
import axios from 'axios'
import { getUserToken } from '#/auth/auth'
export default {
components: {
ValidationProvider,
ValidationObserver,
BFormInput,
BFormGroup,
BForm,
BRow,
BCol,
BButton,
BTable,
},
data() {
return {
name: '',
successMessage: '',
showSuccessMessage: false,
loginError: '',
showLoginError: false,
required,
items: [],
}
},
beforeMount() {
this.getAllUsers()
},
methods: {
getAllUsers() {
const API_URL = `${this.$server}/api/twitter/allusers`
const params = {
token: getUserToken(),
}
axios.post(API_URL, null, { params }).then(res => {
if (res.data) {
res.data.forEach(element => {
let isActive = 'active'
if (element.isActive === 0) {
isActive = 'disabled'
}
const arr = {
twitter_name: element.twitter_name,
twitter_username: element.twitter_username,
twitter_id: element.twitter_id,
userActive: isActive,
}
this.items.push(arr)
})
}
})
},
validationForm() {
const API_URL = `${this.$server}/api/twitter/adduser`
const params = {
twitter_username: this.name,
token: getUserToken(),
}
axios.post(API_URL, null, { params }).then(res => {
if (res.data.success) {
this.successMessage = res.data.message
this.showSuccessMessage = true
// Hide message after 5sec
setTimeout(() => {
this.successMessage = ''
this.showSuccessMessage = false
}, 5000)
} else {
this.loginError = res.data.message
this.showLoginError = true
// Hide message after 5sec
setTimeout(() => {
this.loginError = ''
this.showLoginError = false
}, 5000)
}
})
},
},
}
</script>
I'm a little bit confused, where do you want to show your button ?
If it's in the table, you can use the custom templation of Bootstrap-Vue, you'll find the doc here with an example : https://bootstrap-vue.org/docs/components/table#custom-data-rendering
EDIT: here an example for your case
<b-table responsive="sm" :items="items">
<template #cell(userActive)="data">
<b-button v-if="data.userActive">Disabled</b-button>
<b-button v-else>Enabled</b-button>
</template>
</b-table>

Next.js Handling User Logged In Status

I'm using next-iron-session in my next.js project with discord oauth2.
My Session Code:
import {
GetServerSidePropsContext,
NextApiRequest,
NextApiResponse,
} from "next";
import { withIronSession, Session } from "next-iron-session";
export type NextIronRequest = NextApiRequest & { session: Session };
export type NextIronHandler = (
req: NextIronRequest,
res: NextApiResponse
) => void | Promise<void>;
export type NextRoute = (
ctx: GetServerSidePropsContext & { req: { session: Session } },
redirect: string
) => any;
export function withSession(handler: NextIronHandler | NextRoute) {
return withIronSession(handler, {
password: process.env.COOKIE_SECRET as string,
cookieName: "session",
ttl: 15 * 24 * 3600,
cookieOptions: {
secure: process.env.NODE_ENV === "production",
sameSite: "strict",
httpOnly: true,
},
});
}
Auth Handler Code:
import next, { GetServerSidePropsContext } from 'next'
import { withSession } from './session'
export const withAuth = (gssp: any) => {
return async (context: GetServerSidePropsContext) => {
const { req } = context
const user = req.session.user
if (!user) {
return {
redirect: {
destination: '/api/auth/login',
statusCode: 302,
},
}
}
return await gssp(context)
}
}
export const withAuthSsr = (handler: any) => withSession(withAuth(handler))
Dashboard Code:
import { GetServerSideProps, NextApiRequest } from "next";
import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import { NextIronRequest } from "../util/session";
import { User, UserData } from "src/types";
import { developerRoute } from "src/util/redirects";
import { withSession } from "src/util/session";
import Router from "next/router";
import { redirect } from "next/dist/server/api-utils";
import { withAuthSsr } from '../util/AuthHandler'
interface Props {
user?: User;
}
export default function Dashboard(req: NextIronRequest) {
function Icon(icon: string) {
console.log(icon)
}
return (
<>
<Head>
<title>{req.user.user.username} | Dashboard</title>
<link rel="shortcut icon" href={req.user.avatar} />
</Head>
<body>
{
req.user.guilds.map((guild: any) => {
return (
<>
<div className="p-10 items-center justify-center flex flex-center grid grid-cols-2 grid-flow-row sm:grid-cols-1 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-3 gap-5">
<div className="rounded overflow-hidden shadow-lg">
<img className="w-full" src={Icon(guild.icon)} alt="Guild Icon" />
<div className="px-6 py-4">
<div className="font-bold text-center text-xl mb-2">{guild.name}</div>
</div>
<div className="px-6 pt-4 pb-2 items-center content-center justify-center">
<a href="#_" className="relative inline-flex items-center justify-center p-4 px-6 py-3 overflow-hidden font-medium text-indigo-600 transition duration-300 ease-out border-2 border-purple-500 rounded-full shadow-md group">
<span className="absolute inset-0 flex items-center justify-center w-full h-full text-white duration-300 -translate-x-full bg-purple-500 group-hover:translate-x-0 ease">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path></svg>
</span>
<span className="absolute flex items-center justify-center w-full h-full text-purple-500 transition-all duration-300 transform group-hover:translate-x-full ease">Manage Settings</span>
<span className="relative invisible">Manage Settings</span>
</a>
</div>
</div>
</div>
</>
)
})
}
</body>
</>
)
}
export const getServerSideProps: GetServerSideProps = withSession(withAuthSsr(developerRoute))
What's happening now is, if the user is even loggedIn it will redirect for login again, How do i fix that?
What did i do wrong? If the user isn't logged he/she gets redirected.
Next.js Version: 12.0.7
Next-Iron-Session Version: 4.2.0

how I pass a dynamic value to use in a v-if in the parent?

I need "showIMP" to be passed to the parent whenever it updates, it updates when the screen width size changes. For some reason #resize="switchShow" is not getting the function, I would also like to know how I could pass this value on to the father, whenever he changes.
If any one can help <3
father
<template>
<div>
<div>
<Cadastro :caminho="caminho" :nomeEntidade="nomeEntidade"/>
</div>
<ValidationObserver ref="observer" v-slot="{ handleSubmit }">
<Formulario>
<div class="columns is-multiline">
<div class="column is-full-mobile is-two-fifth">
<VInput rules="required|max:100" type="text" label="Nome" v-model="servidor_smtp.nome"/>
</div>
<div class="column is-full-mobile is-one-fifth">
<VSelect :itens="[{value:'1', text:'Produção'}, {value:'2', text:'Homologação'}, {value: 3, text:'Desenvolvimento'}]"
label="Tipo" itemValue="value" itemText="text" v-model="servidor_smtp.ambiente"/>
</div>
<div class="column is-full-mobile is-one-fifth">
<VSelect :itens="[{value:'1', text:'Interno'}, {value:'2', text:'Externo'}]"
label="Tipo" itemValue="value" itemText="text" v-model="servidor_smtp.tipo"/>
</div>
<div class="column is-full-mobile is-narrow">
<div class="columns is-multiline">
<div class="column is-full-mobile is-narrow">
<VSwitch label="Usa TLS?" trueValue="Sim" falseValue="Não" size="is-medium" v-model="servidor_smtp.usar_tls"/>
</div>
<div class="column is-full-mobile is-narrow">
<VSwitch label="Ativo" trueValue="Ativo" falseValue="Inativo" size="is-medium" v-model="servidor_smtp.ativo"/>
</div>
</div>
</div>
<div class="column is-full-mobile is-one-fifth">
<VSelect :itens="[{value:'1', text:'Produção'}, {value:'2', text:'Homologação'}, {value: 3, text:'Desenvolvimento'}]"
label="Tipo" itemValue="value" itemText="text" v-model="servidor_smtp.ambiente"/>
</div>
<div class="column is-full-mobile is-one-fifth">
<VSelect :itens="[{value:'1', text:'Interno'}, {value:'2', text:'Externo'}]"
label="Tipo" itemValue="value" itemText="text" v-model="servidor_smtp.tipo"/>
</div>
</div>
<div class="columns is-multiline">
<div class="column is-full-mobile is-one-quarter">
<VInput rules="required|max:100" type="text" label="Host" v-model="servidor_smtp.host"/>
</div>
<div class="column is-full-mobile is-one-quarter">
<VInput rules="required|max:4" type="number" label="Porta" v-model="servidor_smtp.porta"/>
</div>
<div class="column is-full-mobile is-one-quarter">
<VInput rules="required|max:100" type="text" label="Usuário" v-model="servidor_smtp.usuario"/>
</div>
<div class="column is-full-mobile is-one-quarter">
<VInput rules="required|max:100" type="password" label="Senha" password-reveal v-model="servidor_smtp.senha"/>
</div>
</div>
</Formulario>
<div>
<CaixaBotoes #salvar="handleSubmit(salvar)" caminhoVoltar="/cadastros/servidor-smtp/listagem"/>
</div>
</ValidationObserver>
</div>
</template>
<script>
import { ValidationObserver } from 'vee-validate'
import Formulario from '~/components/Formulario'
import VSwitch from '~/components/inputs/VSwitch'
import VSelect from '~/components/inputs/VSelect'
import VInput from '~/components/inputs/VInput'
import CaixaBotoes from '~/layouts/CaixaBotoes'
import Cadastro from '~/layouts/Cadastro'
import apiClient from '#/utils/apiClient'
import notification from '#/utils/notification'
export default {
name: 'CadastroServidorSmtp',
components: {
ValidationObserver,
VInput,
Formulario,
VSwitch,
VSelect,
Cadastro,
CaixaBotoes
},
// props:{
// showIMP:{
// type: Boolean
// }
// },
computed: {
caminho() {
return this.$store.state.servidorSmtp.caminho
}
},
data() {
return {
servidor_smtp: {
id: this.$route.query.id,
nome: null,
ativo: true,
ambiente: 1,
tipo: 1,
host: null,
porta: null,
usuario: null,
senha: null,
usar_tls: false,
},
nomeEntidade: 'Servidor SMTP'
}
},
methods: {
async salvar() {
try {
if (this.servidor_smtp.id) {
await apiClient.updateServidorSmtp(this.servidor_smtp)
} else {
await apiClient.createServidorSmtp(this.servidor_smtp)
}
this.$router.push({ path: '/cadastros/servidor-smtp/listagem', query: { success: true} })
} catch (err) {
notification.sendNotification('Ocorreu um erro ao salvar, tente novamente!', 'is-danger', 5000)
}
}
},
async created() {
if(this.servidor_smtp.id) {
try {
this.servidor_smtp = await apiClient.getServidorSmtpById(this.servidor_smtp.id)
} catch (err) {
notification.sendNotification('Ocorreu um erro ao buscar, tente novamente!', 'is-danger', 5000)
}
}
}
}
</script>
child
<template>
<ValidationProvider
:vid="vid"
:rules="rules"
v-slot="{ errors }">
<b-field
v-bind="$attrs"
:type="{ 'is-danger': errors[0] }"
:message="errors" #resize="switchShow">
<b-select v-bind="$attrs" v-model="innerValue" expanded>
<option v-for="item in itens"
:key="getItemValue(item)"
:value="getItemValue(item)">
{{ getItemText(item) }}
</option>
</b-select>
</b-field>
</ValidationProvider>
</template>
<script>
import { ValidationProvider } from 'vee-validate'
export default {
components: {
ValidationProvider,
},
props: {
rules: {
type: [Object, String],
default: null
},
itens: {
require: true,
type: Array
},
itemValue: {
required: true,
type: String
},
itemText: {
required: true,
type: String
},
value: {
type: null
},
vid: {
default: null
}
},
mounted() {
this.$nextTick(() => {
window.addEventListener('resize', this.onResize);
})
},
beforeDestroy() {
window.removeEventListener('resize', this.onResize);
},
methods: {
switchShow: function(event) {
if (this.windowWidth<=1250){
this.showIMP = false
}else{
this.showIMP = true
}
console.log("event")
},
onResize() {
this.windowWidth = window.innerWidth
console.log("testing")
},
getItemValue(option) {
const property = this.itemValue
let result = null
if (option[property] != null) {
result = option[property]
}
return result
},
getItemText(option) {
const property = this.itemText
let result = null
if (option[property] != null) {
result = option[property]
}
return result
}
},
data() {
return {
innerValue: null,
windowWidth: window.innerWidth,
showIMP: true
}
},
watch: {
innerValue(newVal) {
this.$emit('input', newVal)
},
value(newVal) {
this.innerValue = newVal
}
},
created() {
if (this.value) {
this.innerValue = this.value
}
}
}
</script>
thank you for the patience
You can emit an event about changing showIMP:
if (this.windowWidth<=1250){
this.showIMP = false
}else{
this.showIMP = true
}
this.$emit('onShowIMPChanged', this.showIMP);
and catch this event in a parent component:
<child #onShowIMPChanged="onShowIMPChanged" ...
...
methods: {
onShowIMPChanged(showIMP) {
}
}

vuejs vue-multiselect can't display selected item pass value array of selected objects

I have a field component that is utilized by both edit or create component. in field component i used Vue-multiselect 2.1.4 plugin to show dropdown with multi-select options here is my code
<template>
<div class="col-md-12">
<div class="alert alert-danger alert-dismissible" v-if="errors.length && displayErrors">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-ban"></i> Please correct the following error(s):</h4>
<ul>
<li v-for="error in errors">{{ error }}</li>
</ul>
</div>
<div class="form-group">
<label>Title<span class='red'>*</span></label>
<input type="text" v-model="fields.title" class="form-control">
</div>
<div class="form-group">
<label>Description<span class='red'>*</span></label>
<input type="text" v-model="fields.description" class="form-control">
</div>
<div class="form-group">
<label>Categories<span class='red'>*</span></label>
<multiselect
v-model="fields.category"
:options="categories"
:value="prevGameCategory"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:preserve-search="true"
placeholder="Pick some"
label="name"
track-by="id">
</multiselect>
</div>
<div class="form-group">
<label>Game Grade Levels<span class='red'>*</span></label>
<multiselect
v-model="fields.level"
:options="gameLevel"
:value="prevGameLevel"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:preserve-search="true"
placeholder="Pick some"
label="name"
track-by="id">
</multiselect>
</div>
</div>
And here is my script code
<script type="text/javascript">
import router from '../../router';
import Multiselect from 'vue-multiselect'
import ClassicEditor from '#ckeditor/ckeditor5-build-classic'
import VueCkeditor from 'vue-ckeditor5'
export default {
props: [
'categories',
'gameLevel'
],
mounted() {
if (this.$route.params.id) {
this.isEdit = true
this.getGameById(this.$route.params.id)
}
},
data () {
return {
data: {},
prevGameLevel: [],
prevGameCategory: [],
baseUrl: window.BreakOut.baseUrl,
isEdit: false,
errors: [],
displayErrors: false,
image: '',
fields: {
title: null,
description: null,
category: [],
},
editors: {
classic: ClassicEditor
}
}
},
methods: {
async getGameById(game_id) {
let urlArr = _.split(window.BreakOut.routes.admin_game_edit, '/', 3)
let end_point = _.join(urlArr, '/')+'/'+game_id
let url = this.baseUrl+'/'+end_point
await axios.get(url).then((response) => {
this.data = response.data
this.fields.title = this.data.title
this.fields.description = this.data.description
if (_.isArray(this.data.game_category)) {
if (this.data.game_category.length > 0) {
_.forEach(this.data.game_category, (value, index) => {
this.prevGameCategory.push(_.pick(value.category, ['id', 'name']))
})
}
}
if (_.isArray(this.data.game_grade_level)) {
if (this.data.game_grade_level.length > 0) {
_.forEach(this.data.game_grade_level, (value, index) => {
this.prevGameLevel.push(_.pick(value.grade_level, ['id', 'name']))
})
}
}
// here i have get previous selected objects
console.log(this.prevGameLevel)
console.log(this.prevGameCategory)
}).catch((error) => {
this.$awn.alert(error)
})
},
}
}
In my code what am missing i almost follow plugin doc but the selected items were not displayed
You should not use both v-model and :value simultaneously. You can do:
<multiselect
v-model="fields.category"
:options="categories"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:preserve-search="true"
placeholder="Pick some"
label="name"
track-by="id">
</multiselect>
and set this.fields value at the end of getting data function:
await axios.get(url).then((response) => {
this.data = response.data
this.fields.title = this.data.title
this.fields.description = this.data.description
if (_.isArray(this.data.game_category)) {
if (this.data.game_category.length > 0) {
_.forEach(this.data.game_category, (value, index) => {
this.prevGameCategory.push(_.pick(value.category, ['id', 'name']))
})
}
}
if (_.isArray(this.data.game_grade_level)) {
if (this.data.game_grade_level.length > 0) {
_.forEach(this.data.game_grade_level, (value, index) => {
this.prevGameLevel.push(_.pick(value.grade_level, ['id', 'name']))
})
}
}
// here i have get previous selected objects
console.log(this.prevGameLevel)
console.log(this.prevGameCategory)
this.fields = {
...this.fields,
category: this.prevGameCategory,
level: this.prevGameLevel
}
}).catch((error) => {
this.$awn.alert(error)
})

how to do filter and pagination in the vuejs

i want to do filter and pagination in my view-candidates page..i want to display the candidates depending on the name and experience and expected ctc..i want to display the candidates..
Can anyone help me how to do that in vuejs...
Here is my view-candidates.blade.php
<div class="container">
<div class="row">
<el-row :gutter="12">
<el-col>
<p>View Candidates</p>
</el-col>
</el-row>
<el-row :gutter="12">
<template v-for="c in candidates">
<el-col :span="6">
<Candidate :c="c" :key="c.id"></Candidate>
</el-col>
</template>
</el-row>
</div>
here is my view-candidates.js page:
import Candidate from './components/Candidate.vue';
const app = new Vue({
el: '#app',
data() {
return {
candidates: window.data.candidates,
sortKey : 'first_name'
}
},
components: { Candidate },
});
here is my candidate.vue page:
<template>
<ElCard>
<div slot="header">
<strong>
{{c.first_name.toUpperCase() + ' ' + c.last_name.toUpperCase()}}
<br />
<small>{{c.role}} - {{c.experience}} Years</small>
</strong>
</div>
<p><strong>{{c.contact_no}} : {{c.email}}</strong></p>
<p>
<strong>Currently at:</strong> {{c.current_location}}
<br />
<strong>Ready to move:</strong> {{c.desired_location}}
</p>
<ElButton type="primary" size="small" #click="ResumeDialog = true">VIEW RESUME</ElButton>
<ElDialog class="text-left" :title="c.first_name.toUpperCase() + ' ' + c.last_name.toUpperCase()" v-model="ResumeDialog">
<p><strong>{{c.role}} - {{c.experience}} Years</strong></p>
<p>
<strong>Currently at:</strong> {{c.current_location}}
<br />
<strong>Ready to move:</strong> {{c.desired_location}}
</p>
<p>{{c.resume}}</p>
<br />
<p><strong>{{c.contact_no}} : {{c.email}}</strong></p>
</ElDialog>
</ElCard>
//script
import { Button as ElButton, Dialog as ElDialog, Card as ElCard } from 'element-ui';
import axios from 'axios';
export default {
props: ['c'],
data() {
return {
ResumeDialog: false,
}
},
components: { ElButton, ElDialog, ElCard },
}
Can anyone help me how to do that..
TIA..
In your view-candidates.js it should be like that:
import Candidate from './components/Candidate.vue';
const app = new Vue({
el: '#app',
data() {
return {
sortKey : 'first_name',
page: 0,
itemsPerPage: 4,
}
},
components: { Candidate },
methods: {
//custom method bound to page buttons
setPage(page) {
this.page = page-1;
this.paginedCandidates = this.paginate()
},
paginate() {
return this.filteredCandidates.slice(this.page*this.itemsPerPage, this.itemsPerPage * this.page + this.itemsPerPage)
},
},
computed: {
//compute number of pages, we always round up (ceil)
numPages() {
return Math.ceil(this.filteredCandidates.length/this.itemsPerPage);
},
filteredCandidates() {
//filter out all candidates that have experience less than 10
const filtered = window.data.candidates.filter((candidate) => {
//e.g.
if(candidate.experience < 10) {
return false;
}
return true;
})
return filtered;
},
paginedCandidates() {
return this.paginate()
}
}
});
And you render the buttons in the template:
<div class="container">
<div class="row">
<el-row :gutter="12">
<el-col>
<p>View Candidates</p>
</el-col>
</el-row>
<el-row :gutter="12">
<template v-for="c in paginedCandidates">
<el-col :span="6">
<Candidate :c="c" :key="c.id"></Candidate>
</el-col>
</template>
</el-row>
<el-row>
<!-- setPage is our method defined in methods object -->
<button v-for="n in numPages" #click="setPage(n)">#{{ n }}</button>
</el-row>
</div>
I believe this should do the magic. Probably you'll have to adjust it a little bit to your needs.