Ability to toggle True/False with ( v-if ) in the loop - javascript

I am asking about hiding and showing an element in Vue.js
I always use this
<ele v-if="value" />
and then set {value} in Vue Instance data object, then toggle True/False for toggle visible, but now in my situation , my v-if condition put in some element , then this element create with v-for directive
some thing like this
<div v-for="item in items" >
<ele v-if="value" :key="item.i" />
<ele v-if="value" :key="item.i" />
<ele v-if="value" :key="item.i" />
// this button fire a method for Change (toggle) value (used for v-if)
<button #click="ToggleValue" > update </button>
</div>
In my view i have a table contain some rows and each rows have some field ( all field have v-if directive ) and in each rows we have button for fire method
Now what is my question ?!!
At the end my table is doing this , when click on every button ToggleValue method execute and toggle value of (value) object , now all field in all rows change the value ( all thing doing right :D )
but I want click on every button in each row just change the value of that row
I have dummy way
< ele v-if="value(item.id)" />
.........
.........
<button #click="ToggleValue(itme.id)" >
if my index of loop is Const and static I use this way , but now items in loop are dynamic
all thing was in my pen at here , thanks for give me your time
https://codepen.io/hamidrezanikoonia/pen/OQGrPB?editors=1100

Instead of having a single value, turn value into an object (or array) and index it by item.id.
Updated codepen: https://codepen.io/acdcjunior/pen/MQRZmK?editors=1010
In your pen, the JavaScript:
...
],
update_:false
},
methods: {
set_update() {
this.update_ = !this.update_;
}
}
becomes:
...
]
update_: {1: false, 2: false, 3: false}
},
methods: {
set_update(id) {
this.update_[id] = !this.update_[id];
}
}
And the template:
<td :key="getValue.id+4" v-if="update_" mode="in-out" > {{ getValue.rate_curr }} </td>
...
<button #click="set_update()" type="button" class="btn btn-primary"> Update </button>
becomes:
<td :key="getValue.id+4" v-if="update_[getValue.id]" mode="in-out" > {{ getValue.rate_curr }} </td>
...
<button #click="set_update(getValue.id)" type="button" class="btn btn-primary"> Update </button>

Related

Apply click spinner only to one button - Angular

I have a list in a table with button to view a PDF requested from server and I want to make a spinner until the document is received.
I made it to work, but when I click on a button, the spinner appears on all buttons, not only the one I clicked.
Angular
<button (click)="preview(key)">
<div
*ngIf="!this.isLoading"
>
<mat-icon>visibility</mat-icon>
<p>View</p>
</div>
<mat-spinner
*ngIf="this.isLoading"
color="accent"
[diameter]="20"
></mat-spinner>
</button>
isLoading: boolean = false
preview(key: any) {
this.isLoading = true
}
isLoading goes 'false' in another method when the document is received.
you have to pass an id to the preview function so that you can track which row has the spinner, then you will set the isLoading to that value! (you can use the row's index context property)
<td mat-cell *matCellDef="let key = index">
<button (click)="loadingRow = key">
<div *ngIf="!(loadingRow == key)">
<mat-icon>visibility</mat-icon>
<p>View</p>
</div>
<mat-spinner *ngIf="loadingRow == key"
color="accent" [diameter]="20">
</mat-spinner>
</button>
</td>
loadingRow: number | null = null
then after the .pdf is loaded you have to return the flag 'loadingRow' to null

Data repeating in different drop-downs : Vue.js

I have one add button, on clicking that button one dropdown should add automatically, and then if I click it again it should again add that dropdown.
When one dropdown is added I chose one option from available options and then I clicked the add button again to add one more dropdown below it, the dropdown gets added but it is added with the option that I chose for the first dropdown.
Code:
HTML:
<div>
<button class="button btn-primary" #click="addRow">Add row
</button>
</div>
<div class="form-group row" v-for="(row,index) in addRowArr">
<div class="col-md-3">
<label>DropDown: </label>
<b-input-group left="<i class='fa fa-location-arrow'></i>">
<basic-select :options="SupplyChainArray" :selected-option="SupplyChaindata"
#select="SupplyChainobject" v-model="SupplyChain" name="SupplyChain"
id="SupplyChain" placeholder="Select SupplyChain">
</basic-select>
</b-input-group>
</div>
</div>
Javascript:
export default{
data(){
return(){
addRowArr : [],
SupplyChainArray : [{value:1, text:"B2C_HEAVIES"},
{value:2, text:"second"},
{value:3, text:"third"}],
SupplyChaindata: {},
SupplyChain: '',
}
},
methods:{
addRow(){
this.addRowArr.push({})
},
SupplyChainobject(obj) {
this.SupplyChaindata = obj;
this.SupplyChain = obj.value;
},
}
}
For reference please view the attached image :
It is because you are using a v-model with the same variable for all your dropdowns.
You have to use a different variable por each dropdown. According to your data model maybe SupplyChain must be an object with key->value where key is your SupplyChainArray.text and value is the variable associated to v-model.
<basic-select :options="SupplyChainArray" :selected-option="SupplyChaindata"
#select="SupplyChainobject" v-model="row.value" name="SupplyChain"
id="SupplyChain" placeholder="Select SupplyChain">
</basic-select>

All buttons effect only the first button, but not themselves

card.vue is the template with the toggleLike method and the button tag
<template>
<div
class="p-24 grid grid-cols-1 sm:grid-cols-1 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-3 gap-12"
>
<div
v-for="movie in movies"
:key="movie.imdbID"
>
<card :movieData="movie" />
</div>
</div>
</template>
I have dynamically generated buttons, but whichever I click, every time the first one gets "selected" or diselected (depends on its previous state).
I want to toggle them independently.
<button #click="toggleLike()" class="mr-2">
<i id="but" class="fa-thumbs-up" :class="{ fas: isLiked, far: !isLiked }"></i>
toggleLike() {
if(this.movieData.likes == 0) {
$('#but').removeClass('far');
$('#but').addClass('fas');
this.movieData.likes+1;
}
else {
$('#but').removeClass('fas');
$('#but').addClass('far');}
return this.$store.dispatch("updateMovieLikes", {
imdbID: this.movie.imdbID,
});
},
You should put more code on how you structure your generated buttons, is that an array? If it is then your isLiked should be an array
<div v-for="movie in movies">
<button #click="toggleLike(movie)" class="mr-2">
<i id="but" class="fa-thumbs-up" :class="movie.likes === 0 ? 'fas' : 'far'"></i>
</button>
</div>
methods: {
toggleLike(movie) {
movie.likes = movie.likes === 0 ? 1 : 0;
this.$store.dispatch("updateMovieLikes", {
imdbID: this.movie.imdbID,
});
}
}
Edit: Just a tip you dont need jquery in vue
Welcome to SO, You could actually shift-away from jquery with vue. You already made a dynamic class binding on your but element therefore you can remove the jquery class handling on your method.
template:
<button #click="toggleLike()" class="mr-2">
<i class="fa-thumbs-up" :class="isLiked ? 'fas' : 'far'"></i>
</button>
method:
toggleLike() {
// Add here how you handle the toggling of isLiked data
if (this.movieData.likes === 0) this.movieData.likes++;
return this.$store.dispatch("updateMovieLikes", {
imdbID: this.movie.imdbID,
});
},
Note.
I'm not sure how you generate the buttons dynamically, can you show it on your question? (can't comment yet). You should also show how do you handle the toggling of your isLiked data.

Vue JS send data from v-for on button click

I'm new to Vue JS, and i'm having a little problem
i'm looping through an array and i have a button inside the div that i'm looping with
the idea is to get the data of the specified data after the click event
for example let's say i have this array numbers: [1,2,3,4,5] and i'm looping through it like this
<div v-for="number in numbers">
<p>{{ number }}</p>
<button v-on:click="getTheSelectedOne"> Get The Value </button>
</div>
i tried doing so
<button v-on:click="getTheValueOfTheSelectedOne(number)"> Get The Value </button>
but i got an error,
how can i achieve such a result ?
<div v-for="number in numbers">
Should be:
<div v-for="(number, index) in numbers" :key="index">
The following:
<button v-on:click="getTheSelectedOne"> Get The Value </button>
Should be:
<button v-on:click="getTheSelectedOne(number)"> Get The Value </button>
And you must have that method defined:
methods: {
getTheSelectedOne (number) {
// then number will be the number
console.log(number)
}
}

Rendering a dynamic input field in React

I have a quiz form here and would like to add input fields for questions when a user clicks the "Add a question" button.
I've been playing around with the code and have been able to populate the state object with some text. Obviously, the goal is to have this be an input component and then somehow rendering this to the screen.
What I'm struggling with is how to render an actual element to the page. I know it's done in the render method of the component just not exactly sure how.
I think I'm getting close. Any help would be appreciated. The code is below.
Thanks!
var QuizForm = React.createClass({
getInitialState : function() {
return { questions : [] }
},
createQuestion : function() {
this.state.questions.push("Test");
// Adds "Test" to state object.
this.setState({
questions : this.state.questions
});
},
render : function() {
return (
<div className="quiz-form well text-center">
<h1 className="header text-center">Quiz Form</h1>
<ul>
{/* Would like question inputs to show up here */}
</ul>
<button onClick={this.createQuestion} className="add-question-btn btn btn-primary" style={{ marginTop : 40 }}>Add Question</button>
</div>
);
}
Just map your this.state.questions array to the HTML element you want.
For instance, if you want to render <li> elements:
render : function() {
return (
<div className="quiz-form well text-center">
<h1 className="header text-center">Quiz Form</h1>
<ul> // magic happens now
{this.state.questions.map(function(state) {
return <li>{state}</li>
})}
</ul>
<button onClick={this.createQuestion}
className="add-question-btn btn btn-primary"
style={{ marginTop : 40 }}>Add Question</button>
</div>
);
}
See an example.
If you want to render <input> tags, you can use the same technique above, but be mindful of the fact that React treats it as a controlled component.
A React best practice would be to map your state.questions array to a dynamically generated HTML component such as:
render : function() {
return (
<div className="quiz-form well text-center">
<h1 className="header text-center">Quiz Form</h1>
<ul> // magic happens now
{this.state.questions.map(function(state) {
return <li key={state.someId}>{state.question}</li>
})}
</ul>
<button onClick={this.createQuestion}
className="add-question-btn btn btn-primary"
style={{ marginTop : 40 }}>Add Question</button>
</div>
);
}
Please keep in mind that when mapping and rendering dynamic objects in React it's always good to insert a key for each mapped object. So make sure to create that when you're creating the content.
Best Regards,

Categories

Resources