Target element when inside v-for loop Vuejs - javascript

I am trying to build a To-Do list in Vue.js which has 3 columns: To-Do, Doing, Done.
I would like to be able to move an item between columns by clicking on arrows that are inside the list item.
Right now I have a list of objects that I separate in 3 arrays depending on a "status" attribute. I would like to change that attribute when clicking on left/right arrow then refresh the UI with new arrays.
I haven't found the way to target the element that received the click.
<ul>
<li v-for="todo in todoTodos" v-bind:key="todo._id">
<span v-if="todo.importance == 1" class="bg-success"></span>
<span v-else-if="todo.importance == 2" class="bg-warning"></span>
<span v-else-if="todo.importance == 3" class="bg-alert"></span>
<div>
<h3>{{ todo.title }}</h3>
<p>{{ todo.description }}</p>
</div>
<p class="todo__date">Début: {{ todo.datebegin }} - Fin espérée: {{ todo.dateend }}</p>
<div class="todo__actions">
<i #click="editTodo" class="icofont-edit"></i>
<i #click="moveRight" class="icofont-arrow-right"></i>
<i #click="moveLeft" class="icofont-arrow-left"></i>
</div>
</li>
</ul>
My linter prevents me from using v-for + v-if, but I guess that means I will have to re-calculate each list (todoTodos, doingTodos, doneTodos) after each modification. Is there a better way ?
I tried console.logging this e.target e.currentTarget but
this logs the entire data model
e.target and e.currentTarget logs the element which I can't use to find my way back to the todo item I want to modify

You /usually/ pass the ($event) argument to a method if you want to access an event.
<i #click="moveLeft($event)" class="icofont-arrow-left"></i>
......
methods: {
moveLeft(e){
console.log(e.target)
}
}

Related

How to get category value in slot (Vuetify calendar)

I am having trouble figuring out how to have hover functionality in categories view of Vuetify calendar in the body part (slot day-body). Now when I implement the hover functionality, the whole row has the hover, but I am hovering over one category only. Everything else such as the week, day and 4-day is working properly because I can individually get date, week and timeToY from the day-body slot.
<template v-slot:day-body="{ date, timeToY }">
<div :class="{ hover: isHover && date === hoverDate }"
:style="{ top: `${timeToY(hoverY)}px` }">
<p class="mt-2 ml-2">{{ hoverY }}</p>
</div>
</template>
This is the HTML that I am using and these two events #mousemove:time="hoverToSeeTime" and #mouseleave:time="removeHover". In the mousemove handler I assign isHover, hoverDate and hoverY. But I can't grasp how to make individual category tiles hoverable because day-body slot does not have the category key. Am I missing anything?
Thanks in advance.
Use #mousemove:time-category and #mouseleave:time-category instead and category will be available in the event handler. Then you can set a hoverCategory along with the other hover properties:
hoverToSeeTime({ date, time, category }) {
...
this.hoverCategory = category;
...
}
category is available in the slot props:
<template v-slot:day-body="{ date, week, timeToY, category }">
So you can compare the two in the slot template. Adjust that template to use a v-if on the div instead of a conditional class:
<template v-slot:day-body="{ date, week, timeToY, category }">
<div v-if="category == hoverCategory && date === hoverDate"
class="hover" :style="{ top: `${timeToY(hoverY)}px` }"
>
<p class="mt-2 ml-2">{{ hoverY }}</p>
</div>
</template>
Here is an updated codepen

Active class not reactive on the first load using vue.js

So I am building a tab component and using :class to bind the active class like this.
<nav class="tabs__header" >
<ul>
<li>
<a
ref="tabItems"
v-for="(tabItem, idx) in tabs"
:key="tabItem.idx"
:class="{ 'b-active': idx === selectedIndex }"
#click="changeTab(idx)">
<span v-if="icon"> {{ tabIcon }} </span>
{{ tabItem.name }}
</a>
</li>
</ul>
</nav>
The selectedIndex is set with tabIndex value when mounted() for the first time and updated based on the 'idx' selected afterward. I have no problem with the b-active class if we click the tab manually, but it not bind the tabIndex value assigned in mounted().
This is the script I use to directly add value '0' for testing and still not get anything.
props: {
tabIndex: {
type: String,
default: '0'
},
mounted() { this.selectedIndex = this.tabIndex }
can anyone help me? because it seems very simple and I couldn't figure it out for 2 days
The problem solved and it turns out to be the data type problem, apparently tabIndex is a String and selectedIndex is a Number.
I changed:
:class="{ 'b-active': idx === selectedIndex }"
to:
:class="{ 'b-active': idx == selectedIndex }"
and it worked!
At initial render idx seems to be undefined.
Replace this:
:key="tabItem.idx"
With this:
:key="idx"
This now should work fine.
Alternatively, you may use v-for like:
v-for="tabItem in tabs"
Now, using tabItem.idx works just fine as you do in others like tabItem.name.
So, here's your code updated:
<nav class="tabs__header" >
<ul>
<li>
<a
ref="tabItems"
v-for="tabItem in tabs"
:key="tabItem.idx"
:class="{ 'b-active': tabItem.idx == selectedIndex }"
#click="changeTab(idx)">
<span v-if="icon"> {{ tabItem.icon }} </span>
{{ tabItem.name }}
</a>
</li>
</ul>
</nav>

Jquery click function not working for all the ids

I have created a page which contains all the products from the database, and this is dynamic page. Columns are created in loop. Whenever user clicks the product i am fetching the product id which is unique, however this is working only for one product, for next product even if click the function is not triggered. below is the code for reference.
{{ album.product_name }}
Category : {{ album.product_category }}
Price : {{ album.product_price }}
$(document).ready(function() {
$('#k').click(function(){
var a = $('#custId').val();
alert(a)
console.log(a)
});
This is working perfectly fine for the first product only i.e the first product from the loop. for rest the click function is not working. Please help!
Below is the HTML code:
<div class="card-body">
<a href="#" id="k">
<img src="qph.fs.quoracdn.net/…" class="card-img-top" alt="..." height="90px" width="85px" id="k">
</a>
<h5 class="card-title">{{ album.product_name }}</h5>
<p class="card-text">Category : {{ album.product_category }}</p>
<p class="card-text">Price : {{ album.product_price }}</p>
<input type="hidden" id="custId" value={{ album.id }}>
</div>
You cannot have multiple elements with the same ID. Consider adding a common class name to all the target elements, say myClass, then you can bind the desired event using:
$('.myClass').click(function(){
//your code here...
});
Explanation: The browser assumes you only have one element with an id of k (because is should be like so by convention), therefore $("#k") will only target the first element with that ID.

angularjs ng-repeat hide element with a click event

There is a list of items which is displayed using ng-repeat. Each item is associated with a hide link. The intent is to hide an item if its corresponding hide link is clicked.
view:
<div ng-repeat="item in products">
<div>{{ item }}</div>
<a href"javascript:void(0)" ng-click="hideMe(item)">[delete]</label>
</div>
How could I implement the function hideMe(item) such a way that it could hide item div element, something like following, ng-if could identify when to hide based on the click event -
<div ng-if="...">{{ item }}</div>
For every list-item, you want to hide it if it's clicked. The best way we can do this is by adding the ng-hide directive.
Using the ng-click directive on a button, we can set the hidden property of an item to true, meaning it should be hidden.
<ul>
<li ng-repeat="fruit in fruits" ng-hide="fruit.hidden">
<p>{{fruit.name}}</p>
<button ng-click="hideMe(fruit)">hide li</button>
</li>
</ul>
$scope.hideMe = function (fruit) {
fruit.hidden=true;
alert('hide this li');
};
Here is a fiddle
http://jsfiddle.net/5yh8bxay/1/
You could use an array of objects like this: $scope.products = [{name: 'hello', status: true}]
And then you can hide them changing the status property:
<div ng-repeat="item in products">
<div ng-show="item.status">
{{ item.name }} <a href"javascript:void(0)" ng-click="item.status = false">[delete]</label>
</div>
</div>
JSFiddle
You can use $index to do that.
Something like this.
<div ng-repeat="item in products">
<div ng-hide="selected.index === $index">{{ item }}</div>
<a href"javascript:void(0)" ng-click="selected.index = $index">[delete]</label>
</div>
Just store the selected value when clicked and use-hide you can use ng-class to hide the item, comparing them to the selected index.

angularjs ns-show logic flow

I am a newbie in angularjs. I'm trying to show an html element depending on a property of the $scope object but without using any form element.
This is the snipped of code:
<div id="ListApp">
<div ng-controller="ListCtrl">
{{ myData.prova }}: {{ myData.logged }}
<div id="secretContent" ng-show="myData.logged">
<ul>
<li ng-repeat="elemento in lista">
<input type="checkbox" ng-model="elemento.comprato" />
<span ng-if="!elemento.comprato">{{ elemento.nome }}</span>
<span ng-if="elemento.comprato" style="text-decoration:line-through;">{{ elemento.nome }}</span>
</li>
</ul>
<input type='text' id='input_nome'/><button ng-click="aggiungi()">Aggiungi</button>
</div>
</div>
</div>
And this is the controller part:
<script>
var listaViaggio = angular.module('listApp', ['directive.g+signin']);
listaViaggio.controller('ListCtrl', ['$scope',function ListCtrl($scope) {
$scope.lista = [];
$scope.myData={};
$scope.myData.prova="test";
$scope.myData.logged=0;
$scope.aggiungi = function(){
$scope.lista.push({
'nome':document.getElementById("input_nome").value,
'comprato':false
});
};
$scope.$on('event:google-plus-signin-success', function (event, authResult) {$scope.myData.logged=1;console.log($scope.myData.logged);});
$scope.$on('event:google-plus-signin-failure', function (event, authResult) {$scope.myData.logged=0;console.log($scope.myData.logged);});
}]);
</script>
As can be easily seen, I change the status of $scope.myData.logged on google+ sign in and I espect that the div with id secretContent will be shown or won't be shown depending on this property but I've seen that the truthfulness of the ng-show is evaluated only once and is not binded to the actual value of the property, so, when it changes, nothing happens.
What is wrong in my code? Which is the correct logic flow of the ng-show command and how to bind it to a $scope property?
Thanks in advance to everybody.
Use $scope.$apply() whenever the values get changed.
$scope.$apply() will update the page content.

Categories

Resources