In Vue&Vuex, how can I activate onclick method in child component? - javascript

I'm trying to edit JS library that already existed but it consisted of Vue. So I studied Vue a little.
The problem is that I made child component called 'Analysis' and want to anchor function. I made tag and bind 'moveAnchor' method to onclick, also declared 'moveAnchor' on methods part. but it didn't work. How can I fix? I'm sorry for being inexperienced.. :(
it is script.js of analysis.
import { mapActions, mapState } from 'vuex';
export default {
name: 'Analysis',
computed: {
checkName : function(){
var flag = this.$store.state.analysis.name;
if(flag.indexOf("/PCs/") != -1){
console.log(flag);
}
}
},
methods: {
moveAnchor: function (id){
var div = document.getElementById(id).scrollIntoView();
}
it is template.html of analysis.
<div :class="$style.scrollarea">
<div :class="$style.dropdown">
<button :class="$style.dropbtn">Analysess</button>
<div :class="$style.dropContent">
<a v-for="item in analyData" v-bind:key="item.id" #onclick="moveAnchor(item.id)">
{{ item.title }}
</a>
</div>
</div>
<span>
{{ checkName }}
</span>
<div v-for="item in analyData">
<h1 v-bind:id="item.id">{{ item.title }}</h1>
<img v-bind:src="item.src" style="width: 100%; height: auto">
</div>

Welcome to StackExchange!
The correct binding for Vue's click event is v-on:click, or #click for shorthand. So when you write #onclick, Vue will never call that.
Just change #onclick to #click and all should work fine.

Related

VUE- How do I put the values inside of components imported?

I remember I have seen once how to put the values in the html text area after importing components in VUE.
I'm not sure there is a way to do that or I just remember things in a wrong way.
my code is as below.
<template>
<div class="container">
<div class="row">
<Heading></Heading>
</div>
<hr>
<div class="row">
<div class="col-xs-12 col-sm-6">
<ul class="list-group">
<comp v-for='(value,index) in listing' :key='index'>{{value}}</comp>
</ul>
</div>
<serverstat></serverstat>
</div>
<hr>
<div class="row">
<footing></footing>
</div>
</div>
</template>
<script>
import Heading from './assets/Heading.vue';
import comp from './assets/comp.vue';
import serverstat from './assets/serverstatus.vue';
import footing from'./assets/footing.vue';
export default {
data() {
return {
listing: ['max','toms','judy','michael','dumdum']
}
},
components: {
Heading,comp,serverstat,footing
},
};
</script>
<style>
</style>
-comp-
<template>
<li class="list-group-item">
</li>
</template>
<script>
export default {
}
</script>
<style>
</style>
After I render this,
it doesn't show {{value}}. It only shows blank .
How do I insert the {{value}} within the html element?
Thank you in advance.
Since you are entering a value inside of a component, you can render it by using a slot in your component like this:
<template>
<li class="list-group-item">
<slot />
</li>
</template>
<comp v-for='(value,index) in listing' :key='index'>
<slot>{{ value }} </slot>
</comp>
Then in comp component use slot as
<slot/>
Not including the approach for props as you don't want to use that. Use the link above to learn more about slots.
When you use v-for it calls all the value from an array and :key='index' defines each object row from an array. If your object listing consists of firstname, lastname as your object then the value you want to print will be {{value.firstname}}. You are missing object name in value.
Can you try this once :
<comp v-for='(value,index) in listing' :key='index'>{{value.index}}</comp>

Apply an Class by using VueJS condition

I'm trying to apply a class to a <p> tag using a VueJS condition but it doesn't work at all, despite it working on JSfiddle. It's been 3 days now that I'm stuck, please help me.
VueJS (in main.js)
new Vue({
el: "#test",
data: {
selected: "2"
}
});
HTML (App.vue)
<div id="app">
<div id="test">
{{ selected }}
<p :class="{ selection: 1 === selected }">
heyyy 1
</p>
<p :class="{ selection: 2 == selected }">
heyyy 2
</p>
<button #click="selected = 2">Switch</button>
</div>
</div>
I'll assume you're using Vue-CLI since you have a .vue file, but your main.js is using syntax from Vue CDN. Maybe you copied the code from the fiddle instead.
I'll assume too that you have a CSS class named .selection for this to work.
Either way, App.vue has its own component instance which is not the main.js mounting instance (it's one level deeper). Your code creates selected in the mounting root instead of App.vue.
To fix, create it in App.vue <script> section instead:
<template>
<div id="app">
<div id="test">
{{ selected }}
<p :class="{ selection: 1 === selected }">
heyyy 1
</p>
<p :class="{ selection: 2 == selected }">
heyyy 2
</p>
<button #click="selected = 2">Switch</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
selected: "2"
}
}
}
</script>
<style>
.selection {
/* CSS */
}
</style>
to apply class binding in VueJs you can use it as :
:class="{ 'selection(your class name here)': selected === 1}"

Vue component stops working when wrapped into another component

I got stucked with Vue.js. I am trying to basically wrap a component(that is already inside one component) into one more. I have a dropdown with a select and I call a function on change. Everything works fine until I wrap the component in one more on top. The top level one is in blade as it's used with Laravel. Snippets:
Component with dropdown:
<template>
<div id="watchlist-item">
<select #change="changed()" class="form-control"
id="currencies" name="currencyList">
<option value="USD" selected="selected">USD</option>
<option value="EUR">EUR</option>
</select>
</div>
</template>
<script>
export default {
name: "watchlist-item.vue",
methods: {
changed() {
alert("CHANGED");
},
},
}
</script>
Wrapper:
<template>
<div id="watchlistItem">
<watchlist-item></watchlist-item>
</div>
</template>
<script>
export default {
name: "watchlist"
}
</script>
Top component:
<template>
<div id="watchlist">
<watchlist></watchlist>
</div>
</template>
<script>
export default {
name: "main-component"
}
</script>
Blade template:
#extends('layouts.layout')
<div>
{{-- <div id="maincomponent">--}}
{{-- <main-component></main-component>--}}
{{-- </div>--}}
<div id="watchlistItem">
<watchlist-item></watchlist-item>
</div>
</div>
This works fine and i get alert on change. However, when i uncomment the commented part and vice-versa (so basically wrap it one more time) vue stops aletring me. I find this behaviour pretty weird but I am just starting with Vue so maybe its just a small detail I'm missing. I don't really even know what to search for though, so any help would be greatly appreciated. Thank you.
Just make sure that you are importing child components inside it's parent correctly:
main-component > watchlist > watchlist-item
| |
has has
Well it doesnt work because you need to register it via components, but first you need to import it.
<template>
<div id="watchlistItem">
<watchlist></watchlist>
</div>
</template>
<script>
import watchlist from "path/to/watchlist";
export default {
name: "watchlist",
components: {
watchlist: watchlist
}
}

Vue.js call component method results in an error

The problem is the following, I basically have one Component which is 'card' and I the cards are rendered inside a Vue called 'dash' using v-for. Now what I try to do is add an on-click event to the card, and I have a method called expand declared inside my Component but I get an error when I try to do so.
My HTML code looks like this
<div id="dash" class="dash" style="margin-left: 350px; margin-top:50px;">
<div v-for="state in states" class="state slide-in-fwd-center" v-bind:style="{'margin-left' : state.margin + 'px'}">
<h3 class="header">{{state.state}}</h3>
<card v-for="card in state.cards" v-bind:overall_progress="card.overall_progress" v-bind:test_progress="card.test_progress" v-bind:status="card.status" v-bind:practice_progress="card.practice_progress" v-bind:due_date="card.due_date" v-bind:study_progress="card.study_progress" v-bind:key="card.id" v-bind:description="card.description"
v-bind:title="card.title" #click="$emit('expand')"></card>
</div>
</div>
The outer div "dash" is a Vue, that has stated and each state holds an array of cards which are Vue Components. The component looks like this
Vue.component("card", {
props: [
"title",
"description",
"due_date",
"study_progress",
"practice_progress",
"test_progress",
"overall_progress",
"status"
],
template: `TEMPLATE CODE HERE`,
methods: {
calcColor: function(value) {
if(value > 89){
return 'bg-success'
}
else if(value < 90 && value > 39){
return 'bg-info'
}
else{
return 'bg-danger'
}
},
expand : function(){
console.log('123')
}
}
});
While the dash is really simple:
var dash = new Vue({
el: "#dash",
data: {
states: []
}
});
I am not sure what might be the problem since the method I am trying to call is defined inside the methods:{} of the Component 'card' itself it is not in the Vue or global function
firstly it might be easier for you to bind just the whole card object and access it on card component. So instead of this:
<div id="dash" class="dash" style="margin-left: 350px; margin-top:50px;">
<div
v-for="state in states"
class="state slide-in-fwd-center"
v-bind:style="{'margin-left' : state.margin + 'px'}"
>
<h3 class="header">{{ state.state }}</h3>
<card
v-for="card in state.cards"
v-bind:overall_progress="card.overall_progress"
v-bind:test_progress="card.test_progress"
v-bind:status="card.status"
v-bind:practice_progress="card.practice_progress"
v-bind:due_date="card.due_date"
v-bind:study_progress="card.study_progress"
v-bind:key="card.id"
v-bind:description="card.description"
v-bind:title="card.title"
#click="$emit('expand')"
></card>
</div>
</div>
you will have that:
<div id="dash" class="dash" style="margin-left: 350px; margin-top:50px;">
<div v-for="state in states" class="state slide-in-fwd-center" v-bind:style="{'margin-left' : state.margin + 'px'}">
<h3 class="header">{{state.state}}</h3>
<card v-for="card in state.cards"
v-bind:card = "card"
#click="$emit('expand')"></card>
</div>
</div>
For the event, don't use the $emit, try just to call expand, like this:
#click="event_name(argument1, argument2)"
so - for your case:
#click="expand"
Be sure, that you define expand method in the component, you are using it.
in this case - in the parent component, not in the card.

Hide div onclick in Vue.js

What is the Vue.js equivalent of the following jQuery?
$('.btn').click(function(){ $('.hideMe').hide() });
jQuery works out of the box, Vue.js does not. To initialize Vue.js component or App you must bind that component with its data to one specific HTML tag inside your template.
In this example the specified element is <div id="app"></div> and is targeted through el: #app. This you will know from jQuery.
After you declare some variable that holds the toggle state, in this case been isHidden, the initial state is false and has to be declared inside the data object.
The rest is Vue-specific code like v-on:click="" and v-if="". For better understand please read the documentation of Vue.js:
The Vue Instance
Template Syntax
Event Handling
Conditionals
Note: consider reading the whole or at least longer parts of the documentation for better understanding.
var app = new Vue({
el: '#app',
data: {
isHidden: false
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.13/dist/vue.js"></script>
<div id="app">
<button v-on:click="isHidden = true">Hide the text below</button>
<button v-on:click="isHidden = !isHidden">Toggle hide and show</button>
<h1 v-if="!isHidden">Hide me on click event!</h1>
</div>
This is a very basic Vue question. I suggest your read the guide, even the first page will answer your question.
However, if you still need the answer this is how you hide/show elements in Vue.
new Vue({
el: '#app',
data () {
return {
toggle: true
}
},
})
<script src="https://unpkg.com/vue#2.5.3/dist/vue.js"></script>
<div id="app">
<button #click='toggle = !toggle'> click here </button>
<div v-show='toggle'>showing</div>
</div>
<div>
<div>
<button v-on:click="isHidden = !isHidden">Toggle hide and show</button>
<h1 v-if="!isHidden">Hide me on click event!</h1>
</div>
</div>
name: "Modal",
data () {
return {
isHidden: false
}
}
The up-voted answer is definitely a way to do it, but when I was trying to do this it was with a dynamic array instead of a single Div, so a single static Vue variable wouldn't quite cut it.
As #samayo mentions, there isn't a difference between the hide action from jQuery vs Vue, so another way to do this is to trigger the jQuery through the #click function.
The Vue Dev kit will tell you not to mix JS inline with #click events and I had the same problem as #user9046370 trying to put the jQuery command inline with #click, so anyway,
Here's another way to do this:
<tr v-for="Obj1,index in Array1">
<td >{{index}}</td>
<td >
<a #click="ToggleDiv('THEDiv-'+index)">Show/Hide List</a><BR>
<div style='display:none;' :id="'THEDiv-'+index" >
<ul><li v-for="Obj2 in Array2">{{Obj2}}</li></ul>
</div>
</td>
</tr>
Method:
ToggleDiv: function(txtDivID)
{
$("#"+txtDivID).toggle(400);
},
The other perk of this is that if you want to use fancy jQuery transitions you can with this method.
<template>
<button class="btn btn-outline-secondary" type="button"><i class="fas fa-filter" #click="showFilter = !showFilter"></i></button>
</template>
<script>
export default {
methods:{
showFilter() {
eventHub.$emit('show-guest-advanced-filter');
}
}
}
</script>
But it's not worked this method.
<template>
<button class="btn btn-outline-secondary" type="button"><i class="fas fa-filter" #click="filtersMethod"></i></button>
</template>
<script>
export default {
data: () => ({
filter: true,
}),
methods: {
showFilter() {
eventHub.$emit('show-guest-advanced-filter');
this.filter = false;
},
hideFilter() {
eventHub.$emit('hide-guest-advanced-filter');
this.filter = true;
},
filtersMethod() {
return this.filter ? this.showFilter() : this.hideFilter();
}
}
}
</script>
This is worked.

Categories

Resources