I have created a list in my program. In this list, you press ArrowUp or ArrowDown to navigate between the items that are generated with a v-for in said list. When you use the arrows to navigate the list, a counter is used to know which item inside this list is the "selected" one. My current problem is: When you "select" an item that is outside your view, the Browser's Window doesn't follow it down, allowing the selection to keep "going down" this list, but the user isn't able to see the other selected items.
I've tried messing around with the focus() function, but I don't know how to focus() a specific item without using the ref atribute, which I also can't seem to implement since it's being generated with v-for.
Here's my current table:
<table class="table table-striped p-0 m-0" v-show="pedidos.length > 0">
<thead class="table-dark">
<tr class="">
<th>Cliente Emissor</th>
<th>Produto</th>
<!-- <th>Endereço</th> -->
<!-- <th>Valor</th> -->
<th>Data Emissão</th>
<th>Estado</th>
</tr>
</thead>
<tbody>
<template v-for="(pedido, index) in pedidos">
<itemPedido :pedido="pedido" :key="index" :endereco="endereco" :class="[(navegacaoAtual == index) ? 'teste' : '']" ref="teste"></itemPedido>
<itemEdit #atualizarListaPedidos="atualizarListaPedidos" #atualizarStatusModal="atualizarStatusModal" class="animation-dropdown" :pedido="pedido" :key="pedido.nome"></itemEdit>
</template>
</tbody>
</table>
Here's the current navigateWithArrows() function I've made:
navegarSetas(key) {
if (this.navegacaoSetasAtiva == false) {
this.navegacaoSetasAtiva = true
this.navegacaoAtual = 0
} else if (this.modalAtivado == false && this.navegacaoSetasAtiva == true) {
if (key == 'ArrowDown' && this.navegacaoAtual < this.pedidos.length - 1) {
this.navegacaoAtual++
Vue.nextTick().then(() => {
let teste1 = this.$refs.teste[this.navegacaoAtual]
teste1.$el.focus()
})
} else if (key == 'ArrowUp' && this.navegacaoAtual <= this.pedidos.length && this.navegacaoAtual > 0) {
this.navegacaoAtual--
} else if (key == 'Enter') {
let pedidoSelecionado = this.pedidos[this.navegacaoAtual].id
Event.$emit('changeShow', pedidoSelecionado)
}
}
},
All help is appreciated. Thank you!
After taking a break and resuming my search, I stumbled upon something that did exactly what I wanted: the scrollIntoView() function.
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Related
Hello guys specially VueJS devs theres something weird happened. Ill explain it one by one
Full video:
https://drive.google.com/file/d/1G2ksQsMQ1LB868dg29f8mm4NR_x5GycF/view?fbclid=IwAR1YmYbo3J6jHrY6PHd8E_lxA47VJSXV6G3132_uF6Or3bXv7MbnQbRvKaU
I use datatable and then i use this getDefaultPrice() to manipulate the price because the format of my price is like this ("65;75") to return the first value to PHP 65.00
then once i click the add to cart button please see image for codes the getDefaultPrice() also executed.
and I received an error "price.split is not a function" I tried to console.log the function and it really runs it without calling it in my add_to_cart();
<td>
<p>{{getDefaultPrice(product.price)}}</p>
</td>
<td>
<button
class="btn main_bg_color add_to_cart_btn" data-toggle="modal" data-target="#productModal"
#click="add_to_cart(product)"
>
<i class="fa fa-shopping-cart"></i> Add to cart
</button>
</td>
add_to_cart(product) {
this.modal_data = [];
this.modal_data.push(product)
this.modal_data[0].variation = this.modal_data[0].variation.split(';');
this.modal_data[0].price = this.modal_data[0].price.split(';');
this.modal_data[0].drinks_price = this.modal_data[0].drinks_price.split(';');
this.modal_data[0].drinks = this.modal_data[0].drinks.split(';');
},
getDefaultPrice(price) {
console.log("test")
var price_arr = price.split(";");
var default_price = parseFloat(price_arr[0]);
return "PHP " + default_price.toFixed(2);
},
I'm using a Vue Element table to display a list of objects that has an object nested in it.
"main_list":{
"id": "1",
"user": {
"username": "Bob"
}
}
I can display the username using:
<el-table-column prop="user.username" label="User" sortable />
Every now and then this page will throw an error stating that it can not read value username of undefined. This will crash Google Chrome to the extent that you have to kill all Chrome processes in the task manager. Firefox does not crash this bad. I think it goes into an infinite loop
I get the data via API, so it might be that some of the user object does not have any usernames.
So far the the only solution that I have found (I'm not sure it is a solution) is:
<el-table-column prop="username" label="User">
<template
v-if="typeof scope.row.assigned_to !== 'undefined'"
slot-scope="scope"
>{{ scope.row.assigned_to.username }}</template>
</el-table-column>
Do you have any Idea why this crash happens?
Is there a better solution than mine?
Once you fetch the list of items, you should update each one of them so that every user has a defined username - even if it is an empty string. Something like
axios.get(url).then(result =>
this.items = result.data.map(item =>
{
if(!item.user) item.user = {};
if(!item.user.username) item.user.username = '';
return item;
});
You can also try something else:
<el-table-column label="User" sortable :sort-method="sortUsers">
<template slot-scope="tbl">
{{ (tbl.row.user || {}).username || 'UNKNOWN' }}
</template>
</el-table-column>
methods:
{
sortUsers(a, b)
{
const left = (a.user || {}).username || 'UNKNOWN';
const right = (b.user || {}).username || 'UNKNOWN';
if (left < right) return -1;
if (left > right) return 1;
return 0;
}
}
I'm learning Vue.js and I really love it, but I'm currently facing a problem.
I have this code in my template:
<button type="button" class="btn btn-warning ml-auto" v-if="steps.length - 1 == currentStep" #click="submitProject" v-html="paymentAmount">{{model.projectSelectedOptions.length < 1 ? 'Publish without option (free)' : paymentAmount }}</button>
And the paymentAmount computed:
paymentAmount() {
var amount = 0;
this.model.projectSelectedOptions.forEach(function(option) {
if (option == 1) {
option = 19.99
} else if (option == 2) {
option = 9.99
} else {
option = 7.99
}
amount += option;
});
return 'Next : payment (' + amount.toFixed(2) + ' € <span class="price-ht">HT</span>)';
}
My problem is that if I put v-html="paymentAmount" in my button, I never see "Publish without option (free)", just "Next : payment (0 € HT)".
If I remove v-html attribute, I can see "Publish without option (free)" but when I have selected some options, Vue.js render "Next : payment (0 € <span class="price-ht">HT</span>)" (so with raw span).
How should I do it?
EDIT:
For the moment, I added a button with a different v-if condition, but it would be cool if I can do it in one line of code, I don't like the duplicate 😅.
How about putting all your logic inside of your computed property?
HTML part:
<button type="button" class="btn btn-warning ml-auto" v-if="steps.length - 1 == currentStep" #click="submitProject" v-html="paymentAmount"></button>
Vue part:
paymentAmount() {
if(this.model.projectSelectedOptions.length < 1)
{
return 'Publish without option (free)';
}
else
{
var amount = 0;
this.model.projectSelectedOptions.forEach(function(option) {
if (option == 1) {
option = 19.99
} else if (option == 2) {
option = 9.99
} else {
option = 7.99
}
amount += option;
});
return 'Next : payment (' + amount.toFixed(2) + ' € <span class="price-ht">HT</span>)';
}
}
You might use a conditional span as button content:
<button
type="button"
class="btn btn-warning ml-auto"
v-if="steps.length - 1 == currentStep"
#click="submitProject">
<span v-if="model.projectSelectedOptions.length < 1">Publish without option (free)</span>
<span v-else v-html="paymentAmount"></span>
</button>
I'm using mat-radio-button(material2) and I have something like a quiz. When I select an answer and go to the next quiz, the visual effect of unselect is showing in the second quiz. This happens if the selected option in the first quiz, appears in the second too, in the same position or after.
I made a simple example. You can reproduce it selecting "aa", then click ">>" button.
HTML
<mat-radio-group class="example-radio-group" [(ngModel)]="radioSelected">
<mat-radio-button *ngFor="let option of tempSublist" [value]="option" class="example-radio-button" color="primary">
{{option}}
</mat-radio-button>
</mat-radio-group>
<hr>
<button (click)="prev()"><<</button>
<button (click)="next()">>></button>
Typescript
list = [
['aa','bb','cc'],
['cc','aa','bb'],
['bb','cc','ee'],
['dd','bb','cc'],
];
index = 0;
tempSublist = this.list[this.index];
radioSelected:string;
next(){
if(this.index < this.list.length){
this.radioSelected = null;
this.index++;
this.tempSublist = this.list[this.index];
}
}
prev(){
if(this.index >= 1){
this.radioSelected = null;
this.index--;
this.tempSublist = this.list[this.index];
}
}
https://stackblitz.com/edit/angular-7s9qvs?file=app%2Fradio-ng-model-example.html
How can I solve this?
Adding trackBy option on ngFor helps to reduce the transition between the two states. Also disabling repples with [disableRipple]="true" seems to reduce the visual effect:
HTML
<mat-radio-button [disableRipple]="true" *ngFor="let option of tempSublist;
trackBy: trackByFn" ...>
...
Typescript
next() {
if (this.index < this.list.length - 1) {
//add this ^
...
trackByFn(index, item) {
return index;
}
I thought adding a control on navigation buttons would be nice:
<button [disabled]="index <= 0" (click)="prev()"><<</button>
^- this
<button [disabled]="index === tempSublist.length" (click)="next()">>></button>
^- this
Demo
If this is not enough, in last recourse, hide and show the whole block.
Wrap it in a div and set ngIf:
<div *ngIf="isVisible">
<mat-radio-group class="example-radio-group" [(ngModel)]="radioSelected">
...
and use timeout in the class on button click:
next() {
isVisible = true;
this.isVisible = false;
if (this.index < this.list.length - 1) {
...
}
setTimeout(() => this.isVisible = true, 30)
}
Demo
I have the following code in Razor, why doesn't it work?
All I want to do is check to see if data has a value, if it does then print it with to 2 decimal places and append a % sign..
<td>
#if (data.HasValue == true)
{
#string.Format("{0:F2}", data)%
}
</td>
it says I don't need am # at the start of the string. I take that off, then it complain about an ;
but I got it to work by doing the following
#if (data.HasValue == true)
{
<td>
#string.Format("{0:F2}", data)%
</td>
}
else
{
<td>
</td>
}
How can I fix the first set of code to work?
Thanks
Razor has no clue what you want to do with the string.Format call.
To fix that, use:
<td>
#if (data.HasValue == true)
{
#:#string.Format("{0:F2}", data)%
}
</td>
This is guaranteed to work, give it a try:
<td>
#{
if (data.HasValue)// you don't need to compare to true because it's already a boolean :)
{
string.Format("{0:F2}", data)%
}
}
</td>
Try this its working ..
<td>
#if (data.HasValue == true)
{
string.Format("{0:F2} {1}", data, "%");
}
</td>
Or you can try this
<td>
#if (data.HasValue == true)
{
#:#String.Format("{0:F2}", data)%;
}
</td>