I'm a Vue.js noob and trying to figure out how to toggle a class inside a for loop for the parent of the link that is clicked.
I want to click on the "Advanced" link and then toggle a class of overlay for the section and .advanced-fields elements only in that section. I know I can add the onOff data attribute to each section but I am saving to a database and don't want to add in unnecessary data fields.
Can anyone point me in the right direction. Thanks.
Here is a simplified version of my code.
<div id="app">
<section v-bind:class="{ overlay: onOff }" v-for="section in sections">
Advanced
<div class="advanced-fields" v-bind:class="{ overlay: onOff }" v-show="onOff">
<fieldset>
<label>
ID
<input type="text" name="section[id]">
</label>
</fieldset>
<fieldset>
<label>
Class
<input type="text" name="section[css_class]">
</label>
</fieldset>
</div>
</section>
</div>
<script>
new Vue({
el: "#app",
data:{
"sections": [
{
"id": "section-1",
"css_class": ""
},
{
"id": "section-2",
"css_class": ''
}
],
"onOff": false
},
methods: {
showAdvanced: function(section) {
this.onOff = !this.onOff;
}
}
});
</script>
This answer Vue bind click that adds active class (and removes from the last one) helped me figure it out.
https://jsfiddle.net/ferne97/n1hfde94/
Here is the updated code that works properly.
<div id="app">
<section v-bind:class="{ overlay: index == isActive }" v-for="(section, index) in sections">
Advanced
<div class="advanced-fields" v-bind:class="{ overlay: index == isActive }" v-show="index == isActive">
<fieldset>
<label>
ID
<input type="text" name="section[id]" v-model="section.id">
</label>
</fieldset>
<fieldset>
<label>
Class
<input type="text" name="section[css_class]" v-model="section.css_class">
</label>
</fieldset>
</div>
</section>
<pre>{{ $data }}</pre>
</div>
<script>
new Vue({
el: "#app",
data:{
"sections": [
{
"id": "section-1",
"css_class": ""
},
{
"id": "section-2",
"css_class": ''
}
],
"isActive": null
},
methods: {
showAdvanced: function(index) {
this.isActive = this.isActive === index ? null : index
}
}
});
</script>
Related
I am trying to display the selected value in a pill badge that can be removed.
I tried using v-for but I keep breaking the form or it display the selected like this:
here is my code:
data()
{
sport: {
name: '',
sportSize: null,
externalId: '',
teamId: null,
},
teamTransformer: teamTransformer,
comboConfig: {
itemPerPage:30
}
additionalSearchField: null,
},
computed:
{
...mapGetters({
getTeamById: "getTeamById"
})
methodds:{
...mapActions({
fetchTeamsByName: "fetchTeamsByName",
fetchTeamtDetails: "fetchTeamDetails",
fetchOfferByName: "fetchOfferByName",
fetchTeamInfo: "fetchTeamInfo"
}),
async onTeamComboSelect({value})
{
this.teamId = value;
this.form.team = value;
this.form.teamId = value;
this.additionalSearchField = {teamId: this.teamId};
await this.fetchTeamInfo({id: this.teamId});
},
}
<div class="creation-form-field creation-form-field--with-error-wrapper">
<label
for="team"
class="inline-3-columns--camp-wizard"
>
<span class="title__field">Client*</span>
<combo-select
id="teams"
v-model="sport.teamId"
api-location="fetchTeamsByName"
api-details-location="fetchTeamDetails"
search-parameter="teamName"
:additional-search-fields="additionalSearchField"
:transformer="teamTransformer"
:config="{
...comboConfig,
searchLabel: 'Search teams',
showDefaultLabelOnSelect: true
}"
class="input input__typeahead"
#on-select-item="onTeamComboSelect"
/>
<input
v-model="sport.teamId"
type="hidden"
name="teamId"
class="form-control"
:data-vv-scope="sections[0].name"
value="team"
>
</label>
<div class="sport-results-decoration">
<div class="results">
<span
v-for="(teamName, key) in sport.teamId"
class="badge badge-pill badge-success"
>
<span>{{ teamName }}</span>
<font-awesome-icon
icon="times"
class="close"
#click="removeTeam()"
/>
</span>
</div>
</div>
</div>
I also tried {{sport.team}} and {{sport.teamId}} but I get
this
this is how my selected item shows up in inspector:
I tried using label but it shows up empty. Please help, how can I solve this problem?
Many thanks for any help :)
in my vue application I have following code:
<div v-if="partner == true && kids == false" class="row">
<input type="text" id="testInput">
</div>
Now when I want to try out this code snippet it does not render the input. I am pretty sure it should because the variables have the right value at this moment.
I also tried this but this does not work either:
<div v-if="partner && !kids" class="row">
<input type="text" id="testInput">
<div>
Is the condition wrong or what is the problem with this code?
Your code is fine:
new Vue({
el: "#demo",
data() {
return {
partner: true,
kids: false
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<div v-if="partner && !kids" class="row">
<input type="text" id="testInput">
</div>
</div>
isCheckAll: false,
methods: {
checkAll: function(){
this.isCheckAll = !this.isCheckAll;
},
updateCheckall: function(){
this.isCheckAll = true;
},
<div class="checkbox-alignment-form-filter">
<input type="checkbox" id="three" class="vh-product" #click='checkAll()' v-model='isCheckAll' />
<label class="productlist-specific" for="three"
> : 2011</label
>
</div>
<div class="checkbox-alignment-form-filter2">
<input type="checkbox" id="four" class="vh-product" #change='updateCheckall()'/>
<label class="productlist-specific" for="four">E0A</label>
</div>
<div class="checkbox-alignment-form-filter3">
<input type="checkbox" id="five" class="vh-product" #change='updateCheckall()'/>
<label class="productlist-specific" for="five">BR</label>
</div>
<div class="checkbox-alignment-form-filter4">
<input type="checkbox" id="six" class="vh-product" #change='updateCheckall()'/>
<label class="productlist-specific" for="six">E11350A</label>
</div>
<div class="checkbox-alignment-form-filter5">
<input type="checkbox" id="seven" class="vh-product" #change='updateCheckall()'>
<label class="productlist-specific" for="seven">E0BR</label>
</div>
How to select check and uncheck all checkboxes, on selecting one checkbox.
I don't know what stopping me to proceed, For every checkbox taken one #click and sub checkboxes also taken one #click. and then in js i am toggling that condition to check and uncheck.
I think you had some problems with your logic, so let me explain this for you:
You need to have a v-model on all of them, to be able to control state updates (whenever a user clicks something it needs to be updated).
You don't need to have two methods for all of this, you can have just one to enable all of the checkboxes. The rest can be handled by v-model.
The following code will enable/disable all of the checkboxes by clicking the first one, and if you click the other ones, it'll just enable/disable that particular checkbox.
<div id="app">
<input type="checkbox" v-model="checkboxes[0]" v-on:click="checkAll()">
<input type="checkbox" v-model="checkboxes[1]">
<input type="checkbox" v-model="checkboxes[2]">
<input type="checkbox" v-model="checkboxes[3]">
</div>
const app = new Vue({
el: "#app",
data: {
// control the state of checkboxes
checkboxes: [false, false, false, false]
},
methods: {
checkAll: function(){
for(let i = 1; i < this.checkboxes.length; i++){
// update all of the checkboxes to the value of the first one.
this.checkboxes[i] = !this.checkboxes[0];
}
}
}
})
your problem was your data handling.
i made you a playable example in CodeSandbox.
with this you are able to control the main checkbox bidirectional.
if all sub checkboxes are true the main checkbox will be set to true as well.
<template>
<div id="app">
<div class="checkbox-group">
<div class="main-checkbox">
<input
type="checkbox"
:name="checkboxes.main.label"
v-model="checkboxes.main.value"
#input="toggleAllCheckboxes()"
/>
<label :for="checkboxes.main.label">{{ checkboxes.main.label }}</label>
</div>
<div
class="sub-checkbox"
v-for="(checkbox, index) in checkboxes.sub"
:key="index"
>
<input
type="checkbox"
:name="checkbox.label"
v-model="checkbox.value"
/>
<label :for="checkbox.label">{{ checkbox.label }}</label>
</div>
</div>
</div>
</template>
<script>
export default {
name: "App",
data: () => ({
checkboxes: {
main: {
value: false,
label: ":2011",
},
sub: [
{
value: false,
label: "E0A",
},
{
value: false,
label: "BR",
},
{
value: false,
label: "E11350A",
},
{
value: false,
label: "E0BR",
},
],
},
}),
computed: {
mainIsChecked: function () {
return this.checkboxes.main.value;
},
allSubsAreChecked: function () {
return this.checkboxes.sub.every((checkbox) => checkbox.value);
},
},
watch: {
allSubsAreChecked: function () {
this.checkboxes.main.value = this.allSubsAreChecked;
},
},
methods: {
toggleAllCheckboxes() {
for (const checkbox of this.checkboxes.sub) {
checkbox.value = !this.mainIsChecked;
}
},
},
};
</script>
If you are working with multiple checkboxes, you should bind them to the same Array using v-model according to the Vue docs. https://v2.vuejs.org/v2/guide/forms.html#Checkbox
In your case, this means that you should have one array managing all the checkboxes except the one which controls selecting them all, that should be handled differently.
Each of those checkboxes should have a value binding as well, telling Vue which value they represent in the array.
You could also store all the possible checkbox values in an array which would help you reducing code duplication in your template.
You can render all 4 checkboxes which can be separately checked using a v-for loop, and manage them with the same v-model.
The checkbox controlling the "all checked" state should be managed with a different v-model. When that checkboxes value changes, we should check/uncheck all the other checkboxes, which can be done easily using a watcher.
Here's an example using this approach https://codesandbox.io/s/inspiring-dijkstra-fzkmn?file=/src/App.vue
export default {
name: "App",
data: () => ({
selectedValues: [],
allChecked: false,
}),
computed: {
isAllChecked() {
return false;
},
allCheckboxOptions() {
return [
{
label: "E0A",
value: "four",
},
{
label: "BR",
value: "five",
},
{
label: "E11350A",
value: "six",
},
{
label: "E0BR",
value: "seven",
},
];
},
},
methods: {
checkAll() {
this.selectedValues = this.allCheckboxOptions.map(
(option) => option.value
);
},
checkNone() {
this.selectedValues = [];
},
},
watch: {
allChecked(isAllChecked) {
if (isAllChecked) {
this.checkAll();
} else {
this.checkNone();
}
},
},
};
<template>
<div id="app">
<div class="checkbox-alignment-form-filter">
<input
type="checkbox"
id="three"
class="vh-product"
v-model="allChecked"
/>
<label class="productlist-specific" for="three"> : 2011</label>
</div>
<template v-for="(checkboxOption, index) in allCheckboxOptions">
<div
:key="checkboxOption.value"
:class="`checkbox-alignment-form-filter${index + 2}`"
>
<input
type="checkbox"
:id="checkboxOption.value"
:value="checkboxOption.value"
v-model="selectedValues"
class="vh-product"
/>
<label class="productlist-specific" for="four">
{{ checkboxOption.label }}
</label>
</div>
</template>
checked: {{ selectedValues }}
</div>
</template>
I have a simple dynamic radio button, in my example 3 are created from returning data.
When a radio value is selected it populates my reactive form with that value, "yes", "no" or "maybe". In theses objects there are other properties that I would like to be sent back as part of the form.
As below I return section, but also want to return sectionCode of the matched section.
Before radio selection is changed my form shows all properties correctly, but obviously I can only pass back one value, so as soon as I do the other object items are lost.
https://stackblitz.com/edit/angular-r4g6uv?file=src%2Fapp%2Fpersonal%2Fpersonal.component.ts
section:[
{
section: "yes",
sectionCode: "1"
},
{
section: "no",
sectionCode: "2"
},
{
section: "maybe",
sectionCode: "3"
}
]
component.html
<div formGroupName="radioButtons" class="form-group col-6 pl-0 pt-3">
<h2 class="mb-2">radioButtons</h2>
<label for="intel-form-submitter" appRequiredLabel>select</label><br />
<div class="form-check-inline" *ngFor="let item of personal.radioButtons.section">
<label for="{{item.section}}" class="col-12 customradio"
><span>{{item.section}}</span>
<input value="{{item.section}}" id="{{item.section}}" type="radio" formControlName="section"/>
<span class="checkmark"></span>
</label>
</div>
</div>
component.ts
createEntry(formBuilder: FormBuilder) {
return this.formBuilder.group({
title: this.personal.title,
creationDate: this.personal.creationDate,
radioButtons: this.formBuilder.group({
section: this.personal.radioButtons.section,
})
});
}
hope this helps you.
Bind the object instead of one value in the object. In Component.html
[value]="item"
Component.html
<form [formGroup]="form" novalidate>
<div formGroupName="radioButtons" novalidate>
<div class="form-check-inline" *ngFor="let item of section">
<label for="{{item.section}}" class="col-12 customradio"
><span>{{item.section}}</span>
<input **[value]="item"** id="{{item.section}}" type="radio" formControlName="section"/>
<span class="checkmark"></span>
</label>
</div>
</div>
<button type="button" (click)="save()" >Save</button>
</form>
{{form.value|json}}
Component.ts
xport class AppComponent implements OnInit {
section = [
{
section: "yes",
sectionCode: "1"
},
{
section: "no",
sectionCode: "2"
},
{
section: "maybe",
sectionCode: "3"
}
];
selectedSection: any;
form: FormGroup;
constructor(public formBuilder: FormBuilder) {}
ngOnInit() {
this.form = this.createEntry();
}
createEntry() {
return this.formBuilder.group({
radioButtons: this.formBuilder.group({
section: this.section[0]
})
});
}
save(){
console.log(this.form)
}
}
Find project in - https://stackblitz.com/edit/k-react-form-radio-test-5bixbv
You can bind the object itself instead of just section name.
<input [value]="item" id="{{item.section}}" type="radio"/>
Demo : https://stackblitz.com/edit/angular-h1mwhe
I have the following fieldsets containing checkboxes:
<fieldset>
<label v-for="(count, value) in availableFilters.level"><input type="checkbox" data-filterName="level" :value="value" v-model="level" #change="(e) => handleCheckbox(e, 'level')"> {{value}} ({{count}})</label>
</fieldset>
<fieldset>
<label v-for="(count, value) in availableFilters.subject"><input type="checkbox" data-filterName="subject" :value="value" v-model="subject" #change="(e) => handleCheckbox(e, 'subject')"> {{value}} ({{count}})</label>
</fieldset>
<fieldset>
<label v-for="(count, value) in availableFilters.delivery"><input type="checkbox" data-filterName="delivery" :value="value" v-model="name" #change="(e) => handleCheckbox(e, 'delivery')"> {{value}} ({{count}})</label>
</fieldset>
Notice there's a bit of repetition here, but it works. Here's my Vue instance:
var vm = new Vue({
el: '#app',
data: {
level: [],
subject: [],
delivery: [],
availableFilters: {
level: {
"UG": 12,
"PG": 12,
}
}
},
...
I want something more like this so I don't have to repeat the same block over again:
<fieldset v-for="(filters, name) in availableFilters">
<label v-for="(count, value) in filters">
<input type="checkbox" :data-filterName="name" :value="value" v-model="name" #change="(e) => handleCheckbox(e, name, value)"> {{value}} ({{count}})
</label>
</fieldset>
However, this doesn't work and it seems that the v-model is not bound to the data property. How do I correctly pass that now? The data property name will be whatever name is.
To with situation you should put that properties (level, subject, delivery) inside an object called selected as follows :
selected: {
level: [],
subject: [],
delivery: []
}
and you should loop using v-for like :
<fieldset v-for="(filters, key,index) in availableFilters">
where the filters represents the value, key represents the key like level and ìndex represents the index such 0, using the key item we could access selected like selected[key] so we could bind the checkbox to that property easily.
Full example
new Vue({
el: '#app',
data() {
return {
selected: {
level: [],
subject: [],
delivery: []
},
availableFilters: {
level: {
"UG": 12,
"PG": 12,
},
subject: {
}
}
}
}
});
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app" class="container">
<fieldset v-for="(filters, key,index) in availableFilters">
<label v-for="(count, value) in filters">
<input type="checkbox" :data-filterName="this[filters]" :value="value" v-model="selected[key]" #change="onchange"> {{value}} ({{count}})
</label>
</fieldset>
<pre>{{selected}}</pre>
</div>