Check if string is in an array of objects VueJS? - javascript

I have a text field where a user can input the value and then on click of a button push the value inside an array. The value i want to test for is the uniqueID. So let's say if the user inputs multiple values including comma or white spaces and one of them matches the uniqueId in the existing array. Then i get an alert.
I tried using some but that didn't quite work. Not sure what i am doing wrong.
Here is a sample pen
new Vue({
el: "#app",
data() {
return {
myArray: [{
title: "Sam",
age: 36,
uniqueId: "GHTR435"
},
{
title: "Max",
age: 44,
uniqueId: "MLKT432"
}
],
inputField: "",
inputArray: []
};
},
methods: {
createArray() {
if (this.myArray.some((el) => el.uniqueID === this.inputField)) {
alert("Heyy!!!!");
} else {
this.inputArray.push(this.inputField.trim().replace(/, +/g, ","));
console.log(this.inputArray);
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet" />
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout justify-center>
<v-flex xs6>
<v-text-field solo v-model="inputField"></v-text-field>
<v-btn #click="createArray">Click Me</v-btn>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
Any help will be appreciated. Thank you.

if (this.myArray.some((el) => this.inputField.split(/[, ]/g).includes(el.uniqueID))

You have an error in your condition. It should be
this.myArray.some((el) => el.uniqueId /* <-- "d" instead of "D" */ === this.inputField)

Related

Getting Child Component Input Data to Parent, gathering into Array in Vue.js?

** For example, here, when I click the button, I will have one more component, it means it will have new data, so I want to gather all info into one array when I press Save Data button, I hope,it's pretty straightforward to understand
<Child v-for="count in btnNumber" :key="count" #showData="getElements" />
<v-btn
color="primary"
elevation="10"
class="space"
large
#click="duplicateEl"
>Add Categ & Key</v-btn
>
v-btn
color="secondary"
elevation="13"
class="btnEl"
dark
large
#click="getResult"
>Save Data</v-btn
** It's getting data from my child component using Emit
methods:{
getElements(emitPayload) {
this.selectedChildCategory = emitPayload.selectedCateg;
this.selectedChildKey = emitPayload.selectedKey;
this.selectedChildLanguage = emitPayload.selectedLang;
this.selectedChildContent = emitPayload.selectedCon;
}
}
duplicateEl() {
this.btnNumber++;
}
You can hold data on parent component, pls take a look at following snippet:
Vue.component('Child', {
template: `
<v-form>
<v-container>
<v-row>
<v-col>
<v-select
:items="categories"
label="Category"
dense
outlined
v-model="content.cat"
#change="setD"
></v-select>
</v-col>
<v-col>
<v-select
:items="keys"
label="Key"
dense
outlined
v-model="content.key"
#change="setD"
></v-select>
</v-col>
<v-col>
<v-select
:items="langs"
label="Lang"
dense
outlined
v-model="content.lang"
#change="setD"
></v-select>
</v-col>
<v-col>
<v-select
:items="contents"
label="Cont"
dense
outlined
v-model="content.cont"
#change="setD"
></v-select>
</v-col>
</v-row>
</v-container>
</v-form>
`,
props: ['conte'],
data() {
return {
content: this.conte,
categories: ['first', 'second', 'third'],
keys: [1,2,3],
langs: ['g', 'h', 'j'],
contents: ['aaa', 'bbb', 'ccc']
}
},
methods: {
setD() {
this.$emit('show', this.content);
},
},
})
new Vue({
vuetify: new Vuetify(),
el: "#app",
data() {
return {
contentFields: [{id: 0, cat: '', key: '', lang: '', cont: ''}],
showData: false
}
},
methods: {
addInput() {
let newI = this.contentFields.length
this.contentFields.push({id: newI, cat: '', key: '', lang: '', cont: ''})
},
getElements(e){
const newData = this.contentFields.map(obj => {
if(obj.id === e.id)
return { ...obj }
return obj
});
},
getResult() {
this.showData = !this.showData
}
}
})
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<div id="app">
<v-app>
<v-main>
<v-container>
<v-btn
color="primary"
elevation="10"
class="space"
large
#click="addInput"
>Add Categ & Key</v-btn>
<v-container v-for="(content, i) in contentFields" :key="i">
<child :conte="content" #show="getElements" />
</v-container>
<v-btn
color="secondary"
elevation="13"
class="btnEl"
dark
large
#click="getResult"
>Save Data</v-btn>
<div v-if="showData">{{ contentFields }}</div>
</v-container>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
Try saving the data on emit event (from get elements) to a new data variable array, and use that array
<template>
<div>
<Child
v-for="count in btnNumber"
:key="count"
#showData="getElements(count)"
/>
<!-- BUTTONS HERE -->
</div>
</template>
<script>
export default {
data() {
return {
elementsEmmitedDataArray: [], // array
};
},
methods: {
getElements(countIndex, emitPayload) {
const data = {
uniqueIndex: countIndex, //or anything unique for each Child component
selectedChildCategory: emitPayload.selectedCateg,
selectedChildKey: emitPayload.selectedKey,
selectedChildLanguage: emitPayload.selectedLang,
selectedChildContent: emitPayload.selectedCon,
};
// check if uniqindex is already exist in array then update it else push new data
const index = this.elementsEmmitedDataArray.findIndex(
(element) => element.uniqueIndex === countIndex
);
if (index !== -1) {
this.elementsEmmitedDataArray[index] = data;
} else {
this.elementsEmmitedDataArray.push(data);
}
},
duplicateEl() {
this.btnNumber++;
},
submitData(){
// use the array
console.log(this.elementsEmmitedDataArray);
}
},
};
</script>

How can I get only the field from a vuetify table to post in axios

How can I get only the field from a vuetify table to post by in axios, I have a table as I show in the following code
<div id="app">
<v-app id="inspire">
<v-card>
<v-card-title>
<v-text-field
v-model="search"
append-icon="mdi-magnify"
label="Search"
single-line
hide-details
></v-text-field>
</v-card-title>
<v-data-table
:headers="headers"
:items="students"
:search="search"
>
<template v-slot:item.status="{ item }">
<v-btn v-if="item.status" #click="add(item)">Add</v-btn>
<v-btn v-else disabled>Temporarily no access</v-btn>
</template>
</v-data-table>
</v-card>
</v-app>
</div>
and from script I have the following code
const app = new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
search: '',
headers: [
{ text: 'Number list', align: 'start', value: 'id'},
{ text: 'Name', align: 'start', value: 'name'},
{ text: 'Options', value: 'status' }
],
students: [
{
id: 1,
name: pedro,
status: activo,
},
{
id: 2,
name: juan,
status: activo,
},
{
id: 3,
name: jose,
status: activo,
},
]
};
},
methods: {
add (item) {
axios.post('http://localhost/list?id=' + item.id)
.then(response => {
this.response = response
}).catch(e => {
console.log(e)
});
},
}
});
What I want to do is that when it is clicked I only sent the id per post with axios but when I click it I get an error in the console that says that item is undefined that is my main error, and as you can see I need it to be first verify that the student's status is active. Below I also add an image of the generated table for further reference.
table reference
Edit
i forgot put
#click="add(item)"
but still doesn´t work, no longer even an error appears in the console even if it has the catch
Try:
<v-btn v-if="item.estado" #click="add(item)">Add</v-btn>
Try 2:
Check first if item is coming through correctly by adding the following line. Maybe this will help in tracking down the problem
<template v-slot:item.status="{ item }">
<p>Debug item text: {{item}}</p>
<v-btn v-if="item.status" #click="add(item)">Add</v-btn>
<v-btn v-else disabled>Temporarily no access</v-btn>
</template>

How to filter with a regex what's the user is typing in a Vuetify combobox to create a chip?

I am trying to allow only a certain regex pattern when the user is typing in a comboox to create or add a new chip (basically for example if you want the user to only be able to add phone number chips).
Full Vue Source code: https://codesandbox.io/s/chips-so-0gp7g?file=/src/domains/experimental/Experimental.vue
Preview: https://0gp7g.csb.app/experimental
Relevant piece of Vue Source Code:
<template>
<v-container>
<v-row>
<v-col>
<v-combobox
v-model="chips"
chips
:delimiters="[',']"
append-icon=""
clearable
hint="Hey I'm a 🥔 hint!"
persistent-hint
label="Type your favorite 🥔s"
multiple
solo
#input="meowInput"
#change="meowInput"
>
<template v-slot:selection="{ attrs, item }">
<v-chip
v-bind="attrs"
close
:color="getColor(item)"
#click:close="remove(item)"
>
<strong>🥔{{ item }}</strong
>
</v-chip>
</template>
</v-combobox>
</v-col>
</v-row>
</v-container>
</template>
<script>
import ColorHash from "color-hash";
export default {
name: "Experimental",
components: {},
data() {
return {
select: [],
chips: [],
search: "", //sync search
};
},
methods: {
meowInput(e) {
console.log(e);
},
getColor(item) {
const colorHash = new ColorHash({ lightness: 0.9 });
return colorHash.hex(item);
},
remove(item) {
this.chips.splice(this.chips.indexOf(item), 1);
this.chips = [...this.chips];
},
},
};
</script>
How can I achieve that behaviour?
The only way I can see this working is to evaluate the input against a regex (I used US numbers here, but you can use whatever you need) and, if it does not pass the regex test, pop the value out of the chips array.
You can see what I did below. Hopefully this gives you something to go off of:
<template>
<v-container>
<v-row>
<v-col>
<v-combobox
v-model="chips"
chips
:delimiters="[',']"
append-icon=""
clearable
hint="Hey I'm a 🥔 hint!"
persistent-hint
label="Type your favorite 🥔s"
multiple
solo
#change="meowInput" // I changed this to #change so it executes when the user hits enter
>
<template v-slot:selection="{ attrs, item }">
<v-chip
v-bind="attrs"
close
mask="###"
:color="getColor(item)"
#click:close="remove(item)"
>
<strong>🥔{{ item }}</strong
>
</v-chip>
</template>
</v-combobox>
</v-col>
</v-row>
</v-container>
</template>
<script>
import ColorHash from "color-hash";
export default {
name: "Experimental",
components: {},
data() {
return {
select: [],
chips: [],
search: "", //sync search
};
},
methods: {
meowInput(e) {
// Test if the input string matches the specified regex pattern
if (!/^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/.test(e)) {
console.log("invalid!");
// Remove from the chips array
console.log(this.chips);
this.chips.pop();
} else {
console.log("phone number");
// Automatically added to the chips array
}
},
getColor(item) {
const colorHash = new ColorHash({ lightness: 0.9 });
return colorHash.hex(item);
},
remove(item) {
this.chips.splice(this.chips.indexOf(item), 1);
this.chips = [...this.chips];
},
},
};
</script>

How to create array of strings in VueJS?

I am using VueJS and Vuetify to create a modal that can accept some strings in the text field. Now what i want to do is to push the input string inside an array on click. So let's say if i input something and click create the resultant array is ['inputValue1'] but if i add another value by separating with a comma, the resultant array should be ['inputValue1', 'inputValue2'] instead i am getting it as ['inputValue1', 'inputValue1' 'inputValue2']. So the new value should be pushed to the new index instead of adding it with the last value.
Here is a demo
new Vue({
el: "#app",
data() {
return {
dialog: false,
inputValue: "",
stringArray: []
};
},
methods: {
createArray() {
if (this.inputValue !== "") {
this.stringArray.push(this.inputValue);
console.log(this.stringArray);
}
},
closeDialog() {
this.dialog = false;
this.inputValue = "";
this.stringArray = [];
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<div id="app">
<v-app id="inspire">
<v-layout justify-center>
<v-flex>
<v-btn color="primary" #click="dialog=!dialog"> Click Me </v-btn>
</v-flex>
</v-layout>
<v-dialog v-model="dialog" width=350>
<v-card>
<v-card-title primary-title>
Create Array
</v-card-title>
<v-card-text>
<span class="title">How to create Array of Strings </span>
<v-layout justify-center>
<v-flex xs11>
<v-text-field v-model="inputValue"></v-text-field>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions class="mt-5">
<v-spacer></v-spacer>
<v-btn #click="closeDialog">CLOSE</v-btn>
<v-btn #click="createArray" :disabled="this.inputValue === ''" color="primary">CREATE</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-app>
</div>
Also on Cancel how can i set the input value and the array to an empty string and an empty array respectively. Thank You. I asked it yesterday but had to delete since i wasn't able to figure out the exact issue.
Your `createArray' method is not attached to any click event. Other than that the code is correct. :)
You should clear the inputValue after the value is pushed to the array like this:
methods: {
createArray() {
if (this.inputValue !== "") {
this.stringArray.push(this.inputValue);
this.inputValue = '';
console.log(this.stringArray);
} else {
console.log('The inputValue is empty')
}
},
closeDialog() {
this.dialog = false;
this.inputValue = "";
this.stringArray = []
}
}
});

Dynamic class and color binding in VueJs?

I have this Custom Sort method that on my divs that arranges them ascending or descending. My question is how can i by default have the icon color greyed out and only once you click on the icon, it turns black while the others remain greyed out something like what vuetify data tables offers https://v15.vuetifyjs.com/en/components/data-tables.
Here is a link to my pen.
new Vue({
el: '#app',
data() {
return {
headers: [{
text: "Name",
value: "name"
}, // changed this to name
{
text: "Grades",
value: "grades"
}
],
labels: ["Andy", "Max", "John", "Travis", "Rick"],
Grades: [99, 72, 66, 84, 91],
sortKey: "", // added a sortKey,
direction: 1
}
},
computed: {
tableItems() {
let retVal = this.labels.map((label, i) => {
return {
name: label,
grades: this.Grades[i]
};
});
// if there is a sortKey use that
if (this.sortKey) {
retVal.sort((a, b) =>
this.direction * // here multiply by the direction
(a[this.sortKey] < b[this.sortKey] ? -1 : 1)
);
}
return retVal;
}
},
methods: {
sortBy(prop) {
if (this.sortKey === prop) {
this.direction *= -1 // change direction to -ve or positive
}
this.sortKey = prop;
console.log(prop);
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet" />
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout>
<v-flex v-for="header in headers" :key="header.text" xs4 py-1>
<span>
{{ header.text }}
<v-icon small #click="sortBy(header.value)">arrow_upward</v-icon>
</span>
</v-layout>
<v-layout v-for="item in tableItems" :key="item.name">
<v-flex xs4 py-1>
<span>{{ item.name }}</span>
</v-flex>
<v-flex xs4 py-1>
<span>{{item.grades}}</span>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
I am trying to replicate what vuetify data table offers but i am not able to figure out how would bind the color to the icon. i Just want to set the color of the icon and then change it to black or grey when it is clicked based on the header value.
This is low-tech but you could control the color with a (dynamic, bound) classname that keys off a method to test your sortKey (either on the icon itself, or on a parent element).
Forked Pen
:class="{ current: sortKey == header.value }"
You could create a method...
sortIconClass(val) {
return (this.direction===1 && val===this.sortKey)?'black--text':'grey--text'
}
And use it like...
<v-icon small #click="sortBy(header.value)" :class="sortIconClass(header.value)">arrow_upward</v-icon>
Codeply demo
For the icon, you can do something similar...
<v-icon small #click="sortBy(header.value)" :class="sortIconClass(header.value)">{{sortIcon(header.value)}}</v-icon>
sortIcon(val) {
return (this.direction===1 && val===this.sortKey)?'arrow_upward':'arrow_downward'
}
Updated Codeply
The icon itself is a component that has it's own state, you can do the same, create a single file component Icon.vue, then import it into the vue instance you are using right there
<template>
<i #click="setActive" v-bind:class="{ active: isActive }"></i>
</template>
<script>
data() {
return {
active: false
}
},
methods: {
setActive() {
active = true
}
},
computed: {
isActive() {
return active
}
}
</script>
<style scoped>
.active {
/* do whatever */
}
</style>
import:
import Icon from 'wherever/icon/is.vue'
/* ... */
components: {
'icon': Icon,
}

Categories

Resources