Am trying to loop through a list and display them in a grid with four cards.
<div class="grid-x movies">
<div v-for="item in filteredMovie" :key="item.id">
<div class="cell large-4 medium-3 small-12">
<div class="card">
<img v-bind:src="item.cover_image" style="height:100px;width: 100px">
{{ item.name }}<br/>
</div>
</div>
my computed property is
computed:{
items(){
return this.$store.getters.getMovies
},
filteredMovie:function(){
let self= this;
return this.items.filter(function(item){
return item.name.toLowerCase().indexOf(self.search.toLowerCase()) >= 0
|| item.cast.toLowerCase().indexOf(self.search.toLowerCase()) >= 0
|| item.genre.toLowerCase().indexOf(self.search.toLowerCase()) >= 0;
}
)
}
}
}
</div>
but the list doesn't display on the page but when i put the v-for before the grid the list shows but the cards are not in four columns.what could be the problem
You need to put your classes on the looping div:
<div class="cell large-4 medium-3 small-12" v-for="item in filteredMovie" :key="item.id">
Your code in a sample: https://jsfiddle.net/5b6zkLom/
Related
I'm trying to focus on several elements of my form but the first one, despite being applied, returns an error by console.
This is my template:
<div class="container">
<div class="col-xs-12">
<div class="row">
<h1 class="animal-title">Your selection is : </h1>
</div>
<div class="wrapper">
<form class="first-form" #submit.prevent="onSubmit">
<div class="image-wrapper">
<div class="sel-image">
<div v-on:click="imageSelected = true" v-for="item in items" v-bind:key="item.id">
<label>
<input
type="radio"
name="selectedItem"
ref="item"
:value="item.id"
v-model="itemFormInfo.selectedItem"
#change="onChangeItem($event)"
/>
<img v-if="item.id === 1" src="../../assets/1.png" />
<img v-if="item.id === 2" src="../../assets/2.png" />
<img v-if="item.id === 3" src="../../assets/3.png" />
</label>
<p class="cie-animal-subtitle">{{item.name}}</p>
</div>
</div>
</div>
<div class="form-select">
<div v-show="filteredStock && (imageSelected || itemFormInfo.selectedItem) > 0">
<h1 v-if="this.itemName === 'Phone' || this.itemName === 'Tablet'" for="selectedItem" ref="itemVisible">
Select the brand of your <span>{{this.itemName}}</span> :
</h1>
<h1 v-if="this.itemName === 'PC'" for="selectedBreed" ref="itemVisible">
Select the type of your <span>{{this.itemName}}</span> :
</h1>
<select
ref="brand"
class="form-control"
id="selectedBrand"
v-model="itemFormInfo.selectedBrand"
#change="onChangeBrand($event)">
<option v-for="brand in filteredBrand" v-bind:key="brand.name">{{ brand.name }}</option>
</select>
<div v-show="this.isBrandSelected">
<h1>What are you going to use your
<span>{{itemName}}</span> for ?
</h1>
<input
type="text"
id="componentName"
ref="componentName"
class="form-control fields"
style="text-transform: capitalize"
v-model="itemFormInfo.component"
#keypress="formChange($event)"
/>
<div class="loader-spinner" v-if="loading">
<app-loader/>
</div>
</div>
</div>
</div>
<div class="service-options" v-show="isComponentCompleted">
<div class="from-group">
<h1>
Here are the options for your <span>{{this.itemFormInfo.component}}</span> :
</h1>
<div class="services">
<div class="column-service" v-for="option in options" v-bind:key="option.name">
<div class="service-name">{{option.name}}</div>
<div class="service-price">{{option.price.toString().replace(".", ",")}} </div>
</div>
</div>
and here my first method
onChangeItem(event) {
let item = event.target._value;
this.itemName = this.getItemName(item);
if (this.isItemSelected = true) {
this.isItemSelected = false;
this.isComponentCompleted = false;
this.isLoaderFinished = false;
this.itemFormInfo.name = ""
}
this.$refs.item.focus();
},
in this function that I control my first input, the focus is working but it returns me by console the following error:
"this.$refs.item.focus is not a function at VueComponent.onChangeItem"
I have seen some references to similar cases where they involved the reference in a setTimeout or used the this.$nextTick(() => method but it didn't work in my case.
What am I doing wrong?
How can I focus on the next select with ref brand, once I have chosen the value of the first input?
Thank you all for your time and help in advance
How can I focus on the next select with ref brand, once I have chosen the value of the first input?
You want to put focus on brand but your onChangeItem handler is calling this.$refs.item.focus() (trying to focus item). Seems strange to me...
Reason for the error is you are using ref inside v-for.
Docs: When used on elements/components with v-for, the registered reference will be an Array containing DOM nodes or component instances
So the correct way for accessing item ref will be this.$refs.item[index].focus().
Just be aware that right now v-for refs do not guarantee the same order as your source Array - you can find some workarounds in the issue discussion...
I am new to vue I have component which if the endpoint fails, calls my generic 'Error' modal. All this is working fine but I keep getting the following error:
Cannot read property 'focus' of undefined
This only happens for the else part of my method function.
For this specific issue is I my 'failedPrcess' equals any of the following, this is when I get is, all others are fine:
existOrderSearchProdOrders
stockSearchStockLevels
cartFetchCouriers
Code
<template>
<div class="modal fade danger-modal" id="errorModal" tabindex="-1" role="dialog" aria-labelledby="errorModalTitle" aria-hidden="true"
data-keyboard="false" data-backdrop="static" style="z-index: 99999">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content danger-modal-content">
<div class="modal-header danger-modal-headerfooter">An error has occurred</div>
<div class="modal-body">
<p v-if="failedProcess === 'appGetAccount' || failedProcess === 'existOrderSearchProdOrders' || failedProcess === 'stockSearchStockLevels'
|| failedProcess === 'cartFetchCouriers'">
{{ contactTxt | capitalize }}
</p>
<p v-else-if="errorCount < 3">If the error continues, {{ contactTxt }}</p>
<p v-else>As the error has continued, {{ contactTxt }}</p>
<p>
<b>
01234 567890
<br />
Open from 00:00 to 07:00
</b>
</p>
<p>Advising of what you were doing when the error occurred.</p>
</div>
<div class="modal-footer danger-modal-headerfooter">
<a v-if="failedProcess === 'appGetAccount'" ref="logoutButton" class="btn btn-primary" :class="logoutButtClicked" #click="logoutClicked = true" href="/site/logout">
<span v-if="!logoutClicked" id="logoutButtonLabel">Logout</span>
<span v-else id="logoutSpinner">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
Logging out
</span>
</a>
<router-link v-else-if="failedProcess === 'fetchOrderReportDetails'" to="/review" tag="button"
ref="existOrdersButton" class="btn btn-primary" type="button" data-dismiss="modal" #click.native="closeButton">
Return to existing orders
</router-link>
<button v-else-if="errorCount < 3 && (failedProcess !== 'productsFetchProducts' && failedProcess !== 'existOrderSearchProdOrders'
&& failedProcess !== 'stockSearchStockLevels' && failedProcess !== 'cartFetchCouriers')" ref="closeButton" class="btn btn-primary"
type="button" data-dismiss="modal" #click="closeButton">
Close
</button>
<router-link v-else to="/" tag="button" ref="homeButton" class="btn btn-primary" type="button" data-dismiss="modal" #click="closeButton">
Return to homepage
</router-link>
</div>
</div>
</div>
</div>
</template>
<script>
import * as params from '../params';
export default {
name: "ErrorModal",
data() {
return {
contactTxt: 'please contact us on:',
errorCount: 0,
failedProcess: '',
}
},
mounted() {
VueEvent.$on('show-error-modal', (failedProcess) => {
if (this.failedProcess !== failedProcess) {
this.errorCount = 0;
}
this.failedProcess = failedProcess;
$('#errorModal').modal('show').on('shown.bs.modal', this.focus);
});
},
methods: {
focus() {
if (this.failedProcess === 'appGetAccount') {
this.$refs.logoutButton.focus();
} else if (this.failedProcess === 'fetchOrderReportDetails') {
this.$refs.existOrdersButton.$el.focus();
} else if (this.errorCount < 3 && this.failedProcess !== 'productsFetchProducts') {
this.$refs.closeButton.focus();
} else {
this.$refs.homeButton.$el.focus();
}
},
}
}
</script>`enter code here`
I've tried using v-if before and I also had similar problems and the best solution I found was, instead of using v-if/v-else-if/v-else, use v-show instead to perform conditional rendering.
Also, as the Vue.js doc says:
Generally speaking, v-if has higher toggle costs while v-show has higher initial render costs. So prefer v-show if you need to toggle something very often, and prefer v-if if the condition is unlikely to change at runtime.
This is step 1 which will appear & user will select one category from this
<div class="w-100 text-center step-div py-5">
<h3>step 1 </h3>
<p class="step-p"> for Men, Women or Unisex</p>
<div class="container">
<div id="categorytype" class="responsive">
<div v-for="(type,typeIndex) in types" class="filter-slider-div col-4 p-5" #click= "addfiltertype(typeIndex,type.typeslug)">
<img :src="type.typeImage" class="filter-img mx-auto">
<p>{{type.typename}}</p>
</div>
</div>
</div>
</div>
Out put will be something like Men,Women,Both,Kids etc & On click It is saving slug of this type. which I'll share below,
<h3>step 2 </h3>
<p class="step-p">Select your case size</p>
<div class="container">
<div id="categorydials" class="responsive">
<div v-for="(dial,dialIndex) in dials" class="filter-slider-div col-4 p-5" #click= "addfilterdial(dialIndex,dial.dialname)">
<img :src="dial.dialimage" class="filter-img mx-auto">
<p>{{dial.dialname}}mm</p>
</div>
</div>
</div>
In step 2 User will select Size it can be anything,
<h3>step 3 </h3>
<p class="step-p">Select your case colour</p>
<div class="container">
<div id="categorycolors" class="responsive">
<div v-for="(color,colorIndex) in colors" class="filter-slider-div p-5" #click= "addfiltercolor(colorIndex,color.colorslug)">
<img :src="color.colorimage" class="filter-img mx-auto">
<p>{{color.colorname}}</p>
</div>
</div>
</div>
In Step 3 User will select Colour
Now After this I am updating & saving the slug of these categoies in my js in method
Here is code how my Categories are coming from & saving the category slug in typeslugFilter
I used alert Js to check if it's working & saving correctly or not & It's Saving the exact slug,
var filters = new Vue ({
el: '#categorytype',
data:{
types: [
{
typeId: 1,
typename: 'Men',
typeImage: 'assets/images/filter1.png',
typeslug: 'men',
},
{
typeId: 2,
typename: 'Women',
typeImage: 'assets/images/filter2.png',
typeslug: 'women',
},
{
typeId: 3,
typename: 'Watches',
typeImage: 'assets/images/filter3.png',
typeslug: 'both',
}
] },
methods: {
addfiltertype (typeIndex,typeslug) {
this.typeslugFilter = typeslug;
// alert(this.typeslugFilter+ '+' + typeslug);
}
}
});
Consider similar code for other two categories with variable dialnameFilter & colorslugFilter,
Now I am trieng to fetch filtered products using below code it's not working for me as of now
I am getting my products from json file & they are working fine I am using typeslug & dialname as category type in single product details & using productslider as el: element .
<div id="productslider" class="container py-5">
<p>{{typeslugFilter}}</p>
<div v-for="(variant,variantIndex) in variants" v-if="typeslugFilter === typeslug && dialnameFilter === dialname">
<div class="watch-slider-div">
<img :src="variant.variantImage" class="w-100 py-3">
</div>
</div>
</div>
Please help me out in this If any tech geek an help will be appreciated
I'm trying to implement error handling in ASP.NET so that if there is an error the user will get the error message, then be able to go back and have the previous state restored. I'm using ASP.NET Core and Knockout (not my implementation). I want to update "signerFields" with the model from the server (Model.SignersJson). How would I do this?
Signer.js
function SignerViewModel() {
var self = this;
self.signerFields = ko.observableArray([]);
self.guarantorFields = ko.observableArray([]);
self.companyGuarantorFields = ko.observableArray([]);
...
Signer.cshtml
<div data-bind="foreach: signerFields, visible: signerFields().length > 0">
<div class="row">
<div class="col-lg-10">
<div>
#*Header Company signers section*#
<div class="row" data-bind="visible: isCompany() && !anySigner() && !isInvitation()" style="display: none">
<div class="col-lg-4">
<b>FullName</b>
</div>
#*<div class="col-lg-3">
<b>LastName </b>
</div>*#
<div class="col-lg-4">
<b>Role </b>
</div>
<div class="col-lg-3">
<b>Contact_Information</b>
</div>
</div>
</div>
</div>
...
#section scripts
{
<script src="~/Scripts/Signer.js"></script>
var serverSigners = JSON.parse(#Html.Raw(Json.Encode(Model.SignersJson)));
var observableData = ko.mapping.fromJS(serverSigners);
var viewModel = new SignerViewModel();
viewModel.signerFields(observableData); // <-- How?
}
I get no error messages, nothing.
There is a lot of unknowns with this one, but here is a working example using the information we have at hand. One thing I noticed was when creating this sample was that I assumed the data comming from Razor was in an array. and when the array is passed into the mapping component it comes out as an observable array. This meant that the data going into the signerFields was probably not what you were expecting and ended up having an observableArray with one object which itself was an observable array. Adding round brackets to observableData() means that you get the data out of the observable and you can then pass it into the signerFields as an array of objects.
Hope that made sense.
function SignerViewModel() {
var self = this;
self.signerFields = ko.observableArray([]);
self.guarantorFields = ko.observableArray([]);
self.companyGuarantorFields = ko.observableArray([]);
}
var serverSigners = [{'fullname':'Test Name', 'lastName': 'Name', 'role': 'Test Role', 'contactInformation': '123 Seasame Street NY, US', 'isCompany': true, 'anySigner': false, 'isInvitation': false}];
var observableData = ko.mapping.fromJS(serverSigners);
var viewModel = new SignerViewModel();
viewModel.signerFields(observableData());
ko.applyBindings(viewModel)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<div data-bind="foreach: signerFields, visible: signerFields().length > 0">
<div class="row">
<div class="col-lg-10">
<div>
<div class="row" data-bind="visible: isCompany() && !anySigner() && !isInvitation()">
<div class="col-lg-4">
<b>FullName: </b><span data-bind="text: fullname"></span>
</div>
<div class="col-lg-3">
<b>LastName: </b><span data-bind="text: lastName"></span>
</div>
<div class="col-lg-4">
<b>Role: </b><span data-bind="text: role"></span>
</div>
<div class="col-lg-3">
<b>Contact Information: </b><span data-bind="text: contactInformation"></span>
</div>
</div>
</div>
</div>
</div>
</div>
My vue template:
<div
class="col-sm-4 col-xs-6 thumb"
v-for="(photo, index) in photos"
#click.prevent="check(index)"
>
<a class="thumbnail" :class="{'active': photo.checked}">
<img class="img-responsive" :src="photo.picture" alt="">
</a>
</div>
My check() method:
check(index) {
if(!("checked" in this.photos[index]))
this.photos[index].checked = true
else
this.photos[index].checked = !this.photos[index].checked
},
Everything seems correct but it's not working. What could the problem be?
Vue cannot detect changes to an index of an array.
Get a reference to the photo object of the index passed to check() and then use Vue.set() to update the array like so:
check(index) {
let photo = this.photos[index];
if (!("checked" in photo)) {
photo.checked = true
} else {
photo.checked = !photo.checked
}
Vue.set(this.photos, index, photo);
},
Here's a fiddle.
How about just #click.prevent="$set(photo, 'checked', !photo.checked)" and forget the handler?
<div class="col-sm-4 col-xs-6 thumb" v-for="(photo, index) in photos"
#click.prevent="$set(photo, 'checked', !photo.checked)">
<a class="thumbnail" :class="{'active': photo.checked}">
<img class="img-responsive" :src="photo.picture" alt="">
</a>
</div>
If you want to use the handler:
<div class="col-sm-4 col-xs-6 thumb" v-for="(photo, index) in photos"
#click.prevent="check(photo)">
And
check(photo) {
this.$set(photo, 'checked', !photo.checked)
},