Set checkbox selected in Vue - javascript

I am beginner in vue and web developing. I make my app with Laravel and Vue.
I have this code:
created: function () {
let self = this;
self.setActive('tab1');
axios.get(this.$apiAdress + '/api/tasks/create?token=' + localStorage.getItem("api_token"))
.then(function (response) {
self.documentDircionary = response.data.documentDircionary;
self.selectedDocumentDircionary = response.data.selectedDocumentDircionary;
}).catch(function (error) {
console.log(error);
self.$router.push({path: '/login'});
});
<template v-for="(option) in documentDircionary">
<div class="form-group form-row" :key="option.name">
<CCol sm="12">
<input type="checkbox" name="selectedDocuments[]" :id="option.value" /> {{ option.label }}
</CCol>
</div>
</template>
This code show me inputs - and it's work fine.
I have problem with set selected attribute for selected checkbox.
In array selectedDocumentDircionary results from api:
"selectedProducts": [1,2,43]
How can I set checked for only this checkbox, witch selectedProducts?
Please help me

You can use :checked attribute to marked the checkbox checked as per the selectedProducts you have.
Working Demo :
const app = new Vue({
el: '#app',
data() {
return {
selectedProducts: [1, 2, 43],
documentDircionary: [{
name: 'checkbox1',
value: 1,
label: 'Checkbox 1'
}, {
name: 'checkbox2',
value: 2,
label: 'Checkbox 2'
}, {
name: 'checkbox3',
value: 3,
label: 'Checkbox 3'
}, {
name: 'checkbox4',
value: 4,
label: 'Checkbox 4'
}, {
name: 'checkbox43',
value: 43,
label: 'Checkbox 43'
}]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.0/vue.js"></script>
<div id="app">
<template v-for="option in documentDircionary">
<div :key="option.name">
<input type="checkbox" name="selectedDocuments[]" :id="option.value" :checked="selectedProducts.includes(option.value)" /> {{ option.label }}
</div>
</template>
</div>

You can set :checked based on if the id of the current element is in the array:
<template v-for="(option) in documentDircionary">
<div class="form-group form-row" :key="option.name">
<CCol sm="12">
<input type="checkbox" name="selectedDocuments[]" :id="option.value" :checked="selectedProducts.includes(option.value)" /> {{ option.label }}
</CCol>
</div>
</template>

Related

Returning variables from a Vue.js directive

Vue.js has a built-in directive called v-for which is used to literate over list.
HTML code
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
Script code
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
Here, by using the v-for directive, the elements in items array are returned as variables named item. Here, the variables returned by this v-for directive, can be used in the html DOM. How do I create such a custom directive which returns a variable to the html DOM?
Note: I did search for v-for directives source code in the source code of vuejs, but could not find. Please help me to get this as I am very new to vuejs. Thank you.
Edit:
What I currently have?
There are 3 similar input groups for inputting 'First Name', 'Last Name' and 'Address' respectively. Each input field has label, state, disabled, value, and max properties which are stored in a inputOptions array.
<!-- HMTL -->
<b-input-group :prepend="inputOptions.firstName.label">
<b-form-input
:state="inputOptions.firstName.state"
v-model="inputOptions.firstName.value"
:disabled="inputOptions.firstName.disabled"
:maxlength="inputOptions.firstName.max"
></b-form-input>
</b-input-group>
<b-input-group :prepend="inputOptions.lastName.label">
<b-form-input
:state="inputOptions.lastName.state"
v-model="inputOptions.lastName.value"
:disabled="inputOptions.lastName.disabled"
:maxlength="inputOptions.lastName.max"
></b-form-input>
</b-input-group>
<b-input-group :prepend="inputOptions.address.label">
<b-form-input
:state="inputOptions.address.state"
v-model="inputOptions.address.value"
:disabled="inputOptions.address.disabled"
:maxlength="inputOptions.address.max"
></b-form-input>
</b-input-group>
//Script
inputOptions: {
firstName: {
label: 'First Name',
state: true,
value: 'Foo',
disabled: true,
max: 45
},
lastName: {
label: 'Last Name',
state: true,
value: 'Bar',
disabled: true,
max: 45
},
address: {
label: 'Address',
state: false,
value: 'Foo, Bar.',
disabled: true,
max: 255
},
}
What I needed to achieve
For each input-group field, it is needed to provide the property names one by one. Assume that I have created a vue directive called mydirective and code is simplified as follows.
<!-- HMTL -->
<b-input-group v-mydirective="inputOptions.firstName as myProperty" :prepend="myProperty.label">
<b-form-input
:state="myProperty.state"
v-model="myProperty.value"
:disabled="myProperty.disabled"
:maxlength="myProperty.max"
></b-form-input>
</b-input-group>
<b-input-group v-mydirective="inputOptions.lastName as myProperty" :prepend="myProperty.label">
<b-form-input
:state="myProperty.state"
v-model="myProperty.value"
:disabled="myProperty.disabled"
:maxlength="myProperty.max"
></b-form-input>
</b-input-group>
<b-input-group v-mydirective="inputOptions.address as myProperty" :prepend="myProperty.label">
<b-form-input
:state="myProperty.state"
v-model="myProperty.value"
:disabled="myProperty.disabled"
:maxlength="myProperty.max"
></b-form-input>
</b-input-group>
//Script
inputOptions: {
firstName: {
label: 'First Name',
state: true,
value: 'Foo',
disabled: true,
max: 45
},
lastName: {
label: 'Last Name',
state: true,
value: 'Bar',
disabled: true,
max: 45
},
address: {
label: 'Address',
state: false,
value: 'Foo, Bar.',
disabled: true,
max: 255
},
}
HTML
In your template, iterate over the multiple inputOptions using v-for like:
<div id="app">
<b-input-group v-for="option in inputOptions" :key="option.label" :option="option" />
</div>
SCRIPT
Create custom components for the group, input, and label, like:
Vue.component('b-label', {
props: ['label'],
template: '<div>{{ label }}</div>'
})
Vue.component('b-form-input', {
props: ['state', 'value', 'disabled', 'maxlength'],
template: '<input type="text" :value="value" />'
})
Vue.component('b-input-group', {
props: ['option'],
template:
`<div>
<b-label :label="option.label" />
<b-form-input
:state="option.state"
v-model="option.value"
:disabled="option.disabled"
:maxlength="option.max" />
</div>`
})
FIDDLE
Here is a demo on JSFiddle
This is a basic example of how to use components. Whatever transformations you need to do to the strings can be done in the associated components, via computed properties or methods. You can see a demo by clicking the link where I use a computed property to transform the labels into lowercase. That should be enough to get you going.

AngularJS: Hide divs when dropdown is unselected, and output text

I'm still new to AngularJS, and I've tried looking for the solution to my problem but I can't seem to find one that specifically addresses this. Sorry if this has been asked before! And by new, I mean, I'm still pretty clueless on how much of this works.
I have an array of items that I'm displaying with ng-repeat. Each item has a drop down where they can select Yes or No, or leave it unselected. The data is sorted so that anything that's set to Yes or No moves to the top of the list.
I currently also have a checkbox that allows them to Hide an item, which hides it, and moves it to the end of the array, so that it doesn't clutter them up.
I would like to instead have a button that hides all unselected items (a value of neither Yes nor No), instead of making them hide one at a time.
Second: Any item where they've selected Yes should have their names displayed in Field One; Any items where they've selected No should have their names displayed in Field Two.
Here is my code:
var app = angular.module('List', []);
app.controller('MainController', ['$scope', function ($scope) {
$scope.selected = false;
$scope.pList = [
{
id: '1',
title: 'Apples',
checked: false
},
{
id: '2',
title: 'Oranges',
checked: false
},
{
id: '3',
title: 'Bananas',
checked: false
},
{
id: '3',
title: 'Pears',
checked: false
}
];
$scope.pStatus = [
{
stat: 'Unselected',
color: 'black'
},
{
stat: 'Yes',
color: 'green',
},
{
stat: 'No',
color: 'red'
}
];
}]);
<div class="main" ng-controller="MainController">
<div class="container">
<div class="card" ng-repeat="stuff in pList | orderBy: ['checked', 'selectedpStatus', 'id']:false">
<div ng-hide="stuff.checked">
<h2 class="title">{{ stuff.title }}</h2>
<br /><br /><br />
<div class="status" ng-style="{'color':stuff.pStatus.color}">
<select ng-model="stuff.selectedpStatus" ng-options="item.stat for item in pStatus"></select>
</div>
<p class="normal">Hide <label><input type="checkbox" ng-model="stuff.checked" id="{{ stuff.id }}" /></label></p>
</div>
</div>
<br /><br />
<div class="main">
Field One: :{{ stuff.title }}:
<br />
Field Two: :{{ stuff.title }}
</div>
</div>
Thank you for any help!
There are several questions/clarifications I'd typically want to ask, but here's an answer that should guide you further:
Have a property on the scope that stores whether the filter should be applied or not.
You can then filter the array using a filter in the controller, or defined globally. Or, just hide the elements you don't want shown using an ng-if directive on each element.
The logic for showing the title in field 1 vs 2 is simple; the issue is whether you do this for all items, or if you want to somehow select one to show outside of the repeat.
Here's a basic solution though:
<button type="button" ng-click="toggle()">Hide/Show Unselected</button><br>
Hide all: {{ hideAll }}<br />
<div class="card" ng-repeat="stuff in pList | orderBy: ['checked', 'selectedpStatus', 'id']:false"
ng-if="!hideAll || !stuff.selectedpStatus || stuff.selectedpStatus.stat !== 'Unselected'">
<div ng-hide="stuff.checked">
<h2 class="title">{{ stuff.title }}</h2>
<div class="status" ng-style="{'color':stuff.pStatus.color}">
<select ng-model="stuff.selectedpStatus" ng-options="item.stat for item in pStatus"></select>
</div>
stuff.selectedpStatus: {{ stuff.selectedpStatus }}<br>
Field One: {{ stuff.selectedpStatus && stuff.selectedpStatus.stat === 'Yes' ? stuff.title : '' }}<br />
Field Two: {{ stuff.selectedpStatus && stuff.selectedpStatus.stat === 'No' ? stuff.title : '' }}<br />
</div>
</div>
and
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.selected = false;
$scope.hideAll = false;
$scope.pList = [{
id: '1',
title: 'Apples',
checked: false
}, {
id: '2',
title: 'Oranges',
checked: false
}, {
id: '3',
title: 'Bananas',
checked: false
}, {
id: '3',
title: 'Pears',
checked: false
}];
$scope.pStatus = [{
stat: 'Unselected',
color: 'black'
}, {
stat: 'Yes',
color: 'green',
}, {
stat: 'No',
color: 'red'
}];
$scope.toggle = function() {
$scope.hideAll = !$scope.hideAll;
}
});
In a plunkr: https://plnkr.co/edit/PBr753nznrMwsgAIsTwE?p=preview

Vuejs add and remove classes with v-for

i'm making a list of items with vuejs v-for loop. I have some API data from server.
items: [
{
foo: 'something',
number: 60
},
{
foo: 'anything',
number: 15
},
{
foo: 'text',
number: 20,
}
]
Template
<div v-for="(item,index) in items" :key="index">
<div :class="{ active: ????}" #click="toggleActive">
{{ item.foo }}
{{ item.number }}
</div>
</div>
JS
methods: {
toggleActive() {
//
}
}
I need following: When i'm clicking on div add class active, if i have already active class - remove active class.( toggle ). Also i can select multiple items.
How can i do this? I don't have boolean variable in items array, and i shouldn't move item in a separate component
Here you go.
new Vue({
el: "#app",
data: {
items: [{
foo: 'something',
number: 60
},
{
foo: 'anything',
number: 15
},
{
foo: 'text',
number: 20,
}
]
},
methods: {
toggleActive(index) {
let item = this.items[index];
item.active = !item.active;
this.$set(this.items, index, item);
}
}
})
.active {
color: red;
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<div id="app">
<div v-for="(item,index) in items" :key="index">
<div :class="{ active: item.active}" #click="toggleActive(index)">
{{ item.foo }} {{ item.number }}
</div>
</div>
</div>
Here's a JS Fiddle:
https://jsfiddle.net/eywraw8t/250008/
App.vue
<template>
<div>
<div
v-for="(item, i ) in items"
:key="i"
:class="{ active: i === activeItem}"
>
// some looped items from data here
// button for active toggle
<button #click="selectItem(i)"> make item active </button>
</div>
</div>
</template>
Data and Methods
<script>
export default {
data() {
return {
activeItem: null,
};
},
methods: {
selectItem(i) {
this.activeItem = i;
},
},
};
</script>

Vue.js survey using browser back/forward buttons

I'm using Vue.js to create a survey with multiple pages. Everything works, except I need to make browser back/forward buttons to do the same as Previous/Next buttons on the page.
I have googled multiple times, but I couldn't come up with any solution for the moment...
I know that I could use vue-router, but I don't know how to adapt it.
How can I achieve this?
HTML
<!DOCTYPE html>
***head***
<body>
<div id="app">
<h1>{{ survey.title }}</h1>
<div id="survey" v-for="(question, index) in survey.questions">
<div v-show="index === questionIndex">
<h3>{{ question.text }}</h3>
<div v-if="questionIndex === 2">
<input type="text" v-model="userResponses[2]" placeholder="Please enter your location:">
</div>
<div v-else-if="questionIndex === 4">
<select v-model="question4" multiple>
<option v-for="response in question.responses"> {{ response.text }} </option></select>
</div>
<div v-else-if="questionIndex === 5">
<select v-model="question5" multiple>
<option v-for="response in question.responses"> {{ response.text }} </option></select>
</div>
<div v-else>
<ol>
<li v-for="response in question.responses">
<label>
<input type="radio" v-bind:value="response"
v-bind:name="index"
v-model="userResponses[index]"> {{ response.text }}
</label>
</li>
</ol>
</div>
<div id="container">
<button id="left" v-if="questionIndex > 0" v-on:click="prev">Previous</button>
<button id="right" v-on:click="next">Next</button>
</div>
</div>
</div>
<div v-show="questionIndex === survey.questions.length">
<h2>Thank you for taking our survey!</h2>
<p>{{ userResponses }}</p>
<p>{{ question4 }}</p>
<p>{{ question5 }}</p>
</div>
</div>
<footer>© 2018 George Salukvadze for ***</footer>
</body>
</html>
Vue.js
window.onload = survey;
function survey(){
var survey = {
title: 'Welcome to online survey for Liquid!',
questions: [
{
text: "What is your age group?",
responses: [
{text: '15-24'},
{text: '25-34'},
{text: '35-44'},
]
}, {
text: "What is your gender?",
responses: [
{text: 'Male'},
{text: 'Female'},
{text: 'Do not identify'},
]
}, {
text: "Where do you live?",
responses: [
{text: 'Please enter your location'},
]
}, {
text: "Do you like to shop?",
responses: [
{text: 'Yes'},
{text: 'No'},
]
}, {
text: "Select your favorite things to buy:",
responses: [
{text: 'Clothing'},
{text: 'Lingerie'},
{text: 'Shoes'},
{text: 'Devices'},
{text: 'Cars'},
]
}, {
text: "Please select your favorite brands:",
responses: [
{text: 'Sandro'},
{text: 'Maje'},
{text: 'Sony'},
{text: 'Ferrari'},
{text: 'BMW'},
{text: 'Asus'},
]
}
]
};
new Vue({
el: '#app',
data: {
survey: survey,
questionIndex: 0,
userResponses: Array(survey.questions.length),
question4: Array(5),
question5: Array(9),
},
methods: {
next: function() {
this.questionIndex++;
},
prev: function() {
this.questionIndex--;
}
}
});
}
You could use the vue-router as you implied. The simplest solution for your example, though, is to just use the browser's history API. Steps:
When moving to previous/next questions, use history.pushState to add a state to the browser's history:
methods: {
next: function() {
this.questionIndex++;
this.updateHistory(); // added this line
},
prev: function() {
this.questionIndex--;
this.updateHistory(); // added this line
},
updateHistory: function() { // added this method
history.pushState({questionIndex: this.questionIndex}, "Question " + this.questionIndex);
}
}
And now all you have to do is listen to those history state changes. A good spot to hook a listener to this event is the mounted:
mounted: function() {
var vm = this;
window.addEventListener('popstate', function(event) {
vm.questionIndex = (event.state || {questionIndex: 0}).questionIndex;
});
},
And that's it.
Click here for the a demo page at JSBin (check the history button).
You'll find the source for that demo here.

Update the value of a selected object in Vue

I wand to select an option from a multiple select field and update the prozent value of the selected objects:
<div id="assistenzen">
<form>
<select v-model="assistenz" multiple>
<option v-for="option in options" v-bind:value="option">
{{ option.text }}
</option>
</select>
<ul>
<li v-for="(assi, prozent) in assistenz">{{assi.text}}
<input v-model="assistenz" v-bind:value="prozent">
{{assi.prozent}}
</li>
</ul>
</form>
</div>
<script>
var assistenz = new Vue({
el: '#assistenzen',
data: {
assistenz: 'keine Assistenz',
options: [
{ text: 'One', value: 'A', prozent: '0' },
{ text: 'Two', value: 'B', prozent: '0' },
{ text: 'Three', value: 'C', prozent: '0' }
]
},
});
assistenz.config.devtools = true
</script>
This code creates an input for each selected option but, the whole option text is stored in the input as value. Also it does not update the property of the object.
currently i prefer 'watch':
watch: {
multiselect: function(indexes) {
for(var i = 0; i < this.options.length; i++)
this.options[i].show = indexes.indexOf(i) > -1;
}
}
full example:
https://jsfiddle.net/4xq3mj9o/
To update the value of the choosen objects I had reverenze the Item iterated in the for loop and bind the input model to the items value:
<div id="assistenzen">
<form>
<select v-model="assistenz" multiple>
<option v-for="option in options" v-bind:value="option">
{{ option.text }}
</option>
</select>
<ul>
<li v-for="assi in assistenz">{{assi.text}}
<input v-model="assi.prozent">
{{assi.prozent}}
</li>
</ul>
</form>
</div>
<script>
var assistenz = new Vue({
el: '#assistenzen',
data: {
assistenz: 'keine Assistenz',
options: [
{ text: 'One', value: 'A', prozent: '0' },
{ text: 'Two', value: 'B', prozent: '0' },
{ text: 'Three', value: 'C', prozent: '0' }
]
},
});
assistenz.config.devtools = true
</script>
Use vue-multiselect
Just use something like this
<Multiselect :options="Options" :value="Values" :multiple="true" #update="updateMultiValue"> </Multiselect>

Categories

Resources