Increment or decrement #variable.value in angular 8 in ngFor - angular8

i need to increment a number variable with #variable.value
My target is increment or decrement input quantity value, in ngFor of products to buy them.
so this is my code:
<ion-card *ngFor="let product of products">
<ion-card-content>
{{product.prdNote}}
<div class="quantity-container">
<div class="quantity-buttons">
<ion-button (click)="quantityInput.value++">-</ion-button>
<!-- <ion-input type="number" #quantityInput value="quantity" (change)="setQuantity($event)"></ion-input> -->
<ion-input type="number" #quantityInput [value]="product.prdContainer"></ion-input>
<ion-button (click)="quantityInput.value++">+</ion-button>
</div>
<div class="buy">
<ion-button (click)="addToCart(product, quantityInput.value)"> <ion-icon name="cart"></ion-icon>Aggiungi all'ordine</ion-button>
</div>
</div>
</ion-card-content>
</ion-card>
i want increment input value number in ng for, every single input i want increment or decrement with #quantityInput.value++, but didn't work for me.
The error is that:
quantityInput.value Expected a number type
Can i cast #quantityInput.value as number in html ?
There's another way to work?
Thanks

For me, (click)="quantityInput.value++" was parsing error. Following code worked for me.
Try
<ion-button (click)="quantityInput.value=+quantityInput.value+1">+</ion-button>
Here + in +quantityInput.value is used for casting.
Here is the working example

Related

How do I retrieve the value of my key button and row in v-for using Vue.js?

I am new to Vue.js and I trying to learn now to use it. I have 3X3 structure of buttons
I have the following sample code:
<template v-for="row in 3">
<div class="row" :key="row">
<button #click="nextPlayer(button, row)" v-for="button in 3" :key="indexByrow(button, row)" :value="squares[indexByrow(button, row)]" class="square" style="width:40px;height:40px;"></button>
</div>
</template>
When I click, I want to pass the button and row to nextPlayer(button, row), and the indexByrow(button, row) to use those values in the methods, but I don't seem to have any values. My main goal is to change the value name when I click on it.
You need to make the below changes
<template v-for="(row, indx) in 3">
<div class="row" :key="indx">
<button #click="nextPlayer(button, row)" v-for="(button, indexer) in 3" :key="indexer" :value="squares[indexByrow(button, row)]" class="square" style="width:40px;height:40px;"></button>
</div>
</template>
Not sure if indexByrow is a computed property or method.
You need to modify the logic in indexByrow as well based on the above changes

Vue2 generated select triggers event for every other selects

I have a Vue2 project with Buefy extension. Then I have an array of objects which is rendered in the template with one select component for each item. Everything works, but if I trigger #input event on one of the select elements it triggers input event for all selects in the list. I dont understand what is wrong with that.
<div v-for="(inv, index) in pendingInvitations" :key="index" class="columns is-desktop">
<div class="column is-4">{{inv.email}}</div>
<div class="column is-4">
<b-field class="mb-5">
<b-select v-if="invitationRoles"
:input="changeInvitationRole(index)"
v-model="pendingInvitations[index].role"
:placeholder="role">
<option v-for="(value, key) in invitationRoles"
:key="key"
:value="value">
{{ value }}
</option>
</b-select>
</b-field>
</div>
</div>
...
changeInvitationRole(index){
console.log(index);
},
If I change the role and there are three items in the list the console.log() writes 0, 1, 2 as indexes for all items. Why it happens to me? I expect only current itmes index in the log.
Try replacing input with change

Validate array of inputs with Vee-Validate (Vuejs)

The following works:
<li :key="index" v-for="(...) in items">
<input type="text" name="itemFields[]" v-validate="required">
</li>
// ...
<div class="vv-errors">
<ul>
// shows only for last active input
<li v-for="error in errors.collect('itemFields[]')">{{ error }}</li>
</ul>
</div>
If I make some input empty, it shows an error message. But if I then fill some other empty input with text, the error message disappears completely. That should not be the case, because the other input is still empty. To summarize, the error messages only consider the last active input.
How to achieve that the error message shows up if at least one of the inputs is empty?
Actually the issue you are facing is because the name field is same for all your inputs and that should be unique.
Hence while using v-for you could do something as below :
<div v-for="i in 5" >
<input type="text" :name="'email'+i" placeholder="Email" v-validate="'required|email'">
<span class="error" v-if="errors.has('email'+i)">{{errors.first('email'+i)}}
</span>
</div>
Here is a basic example to solve your problem.

mat-accordion with-in component - angular 5

I have a question component with mat-accordion to display question. I'm calling my question component to question-list component.
Everything works great until this point, the issue arises when I'm clicking on question component it is getting open and remain in that state if I'm opening another one also. As per requirement, only one should open at a time.
I see an issue is with the accordion is reside in question component and from question-list, we are looping it with *ngFor so every accordion is having one expension-pannel in it.
My code was working until I had break mine code to two-component from one question-list(parent) and question(chile)
Sample Code:-
question-list.component:
<ng-template ngFor let-data [ngForOf]="questionList" let-i="index" >
<app-question [data]="data"></app-question>
</ng-template>
question.component:-
<mat-accodion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-description style="float:left;">
{{data.description}}
</mat-panel-description>
</mat-expansion-panel-header>
<form>
<div class="row text-left options">
<div class="col-md-6" *ngFor="let option of data.options;">
<mat-checkbox>{{option.description}}</mat-checkbox>
</div>
</div>
</form>
</mat-expansion-panel>
</mat-accodion>
A question is represented by a single expansion panel. A list of questions is represented by an accordion. So your question component should be an expansion panel only, not an accordion. Then you make the accordion part of the question list with the for loop inside the accordion.
Question List:
<mat-accordion>
<ng-container *ngFor="let data of questionList; let i = index">
<app-question [data]="data"></app-question>
</ng-container>
</mat-accordion>
Question:
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-description style="float:left;">
{{data.description}}
</mat-panel-description>
</mat-expansion-panel-header>
<form>
<div class="row text-left options">
<div class="col-md-6" *ngFor="let option of data.options;">
<mat-checkbox>{{option.description}}</mat-checkbox>
</div>
</div>
</form>
</mat-expansion-panel>
#G. Tranter thanks, for your answer, actually this(your suggestion) I already tried and did not got any success, after that I tried the traditional way of doing collapse and expand with self-declared property in to every question object "expanded" by default this will be false to every question and we have used it as ngModel in expansion control, on change the state of one we handle other "expanded" property.
sample here which is working now,
<mat-expansion-panel [(ngModel)]="data.expanded"
name="fieldName" ngDefaultControl (opened)="panelOpenState(data._id)"
[expanded]="data.expanded">
<mat-expansion-panel-header>
<mat-panel-description style="float:left;">
{{data.description}}
</mat-panel-description>
</mat-expansion-panel-header>
<form>
<div class="row text-left options">
<div class="col-md-6" *ngFor="let option of data.options;">
<mat-checkbox>
{{option.description}}
</mat-checkbox>
</div>
</div>
</form>

xpath not finding text inside <div><span>

.//*[contains(text(), "Apply")]
<input type="hidden" value="false" name="needsValidation"/>
<input type="hidden" value="false" name="fullValidationPerformed"/>
<div class="loadingBox hidden">
<div class="paneContent">
<div class="topButtons">
<div class="rightSide">
<div id="saveChangesButton" class="majorButton">
<div>
<div>
<div>
<span class="hidden"/>
Apply Changes
<span class="down"/>
</div>
</div>
</div>
</div>
</div>
Why is it that the xpath string I created doesn't find "Apply" here? It appears that my xpath statement only fails when the text I want to find is inside a "span" tag inside a "div" tag like this.
Can someone help me understand what I'm missing here please?
The reason that contains(text(), 'Apply') does not work is that the element has several text nodes, and the contains function in XPath 1.0 ignores all but the first. (XPath 2.0 would give you an error if there is more than one).
If you want to get an element whose string value contains 'Apply' without also returning its ancestors, the simplest way is to get the last element containing this string:
(//*[contains(., 'Apply')])[last()]