Why all values are not Dynamically Passed in Html using Vue JS? - javascript

I use vue js with laravel.
I pass multiple variables threw vuejs component(template), i can pass few variables successfully.
But few of them not passed, shows Empty("").
HTML (Template):
<template v-if="showTemplate" id="segment_body">
<div class="col-md-2" align="center">
<b>Grid</b><br>
<i class=""></i>Grid |
<i class=""></i>List
</div>
<b>ID : #{{ t_id }}</b><br>
<b>LIST : #{{ t_showList }}</b>
</template>
HTML (Data Source):
<script> var a = { list: false} </script>
<div>
<campaign_segment :t_id=1 :t_showList="a.list"></campaign_segment>
</div>
VueJS :
Vue.component('campaign_segment', {
template: '#segment_body',
props: ['t_showList','t_id']
});
OUPUT :
ID : 1
LIST :
If i click Option "Grid",
OUTPUT :
ID: 1
LIST : False
Why I'm not get the value of list?
Why I only get the value of ID ?
Any other solutions ?

You're running into this issue because you're you're trying to pass in the javascript object directly to the component instead of passing it through the Vue instance.
Check out this bin: http://jsbin.com/fosifo/edit?html,js,output
The only real difference in the bin is that rather than trying to pass a to the component directly here (which won't work b/c the vue instance isn't aware of the data):
<script> var a = { list: false} </script>
<div>
<campaign_segment :t_id=1 :t_showList="a.list"></campaign_segment>
</div>
We pass it in through the vue instance:
In your html:
<script>
var a = {list: false}
</script>
In your javascript:
new Vue({
el: '#app',
data:{
a: a // the `a` value here is referencing that same `var a = {list: false}` in your markup.
}
})
By doing it this way, as the vue instance is being created it's able to bind it's a data property to the globally defined variable a from your markup.
It's essentially the same as doing this:
new Vue({
el: '#app',
data:{
a: {list: false}
}
})

Related

Buefy field does not react on :message param change

I have a Nuxt project with Buefy components. There is a form with some field component which should react on error according the message parameter for this component. But does not. I can see the correct value in debuger but component does not show the message. :message property should work like the in first email example from documentation
The code looks like:
<template #company>
<h2 class="title">{{ $t('general.login.create_company') }}</h2>
<b-field
:type="loginErrors.company_name ? 'is-danger' : ''"
:message="loginErrors.company_name ? loginErrors.company_name : ''"
>
<b-input
v-model="companyName"
name="company_name"
type="text"
autocomplete="off"
:placeholder="$t('general.login.create_company')"
></b-input>
</b-field>
<div class="buttons is-centered">
<b-button type="is-primary is-light" #click="createCompany">Save</b-button>
</div>
</template>
...
data() {
return {
...
loginErrors: {},
error: 'aaaaaa',
};
},
...
async createCompany() {
const result = await this.$api.users.createCompany({company_name: this.companyName});
if( result.error ) {
this.loginErrors.company_name = result.error; // This does not work although the variable has correct value set
this.error = result.error; // This works fine
return false;
}
},
I use this pattern in other components and it works. I dont understand it. thaks for any help.
change detection of data objects in Vue is shallow (top level only)
In vue.js, Dynamically added property to an object is not reactive. Instead we can assign a whole object so that change detection happen.
For a better understanding please go through this official documentation of Vue.
Demo :
new Vue({
el: '#app',
data() {
return {
loginErrors: {}
}
},
mounted() {
this.loginErrors = {
company_name: 'some value'
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p>{{ loginErrors.company_name ? 'is-danger' : 'no-danger' }}</p>
</div>
I don't think Vue components react to object property changed in a direct way, you could try this.$set(this.loginErrors, 'company_name', result.error); instead of this.loginErrors.company_name = result.error;
FYI: https://v2.vuejs.org/v2/guide/reactivity.html?redirect=true#Change-Detection-Caveats
The solution in this case was to update Buefy version from 0.4.11 to 0.4.21. This fix the issue. Another thing is that is causes new issue with :type in combination with grouped param.

Vue JS how to access data variable in script

I am new to vue.js.
and i am using 2.5.13 version.
I'm trying to access my data variable in component file script.
But this give to me a undefined message.
Id attribute in the component returns correct value, but inside script, it would return undefined.
If I want to use that variable, what do I need to do?
Below is my app.js code
import App from './components/App.vue';
new Vue(Vue.util.extend({
router,
data : {
test : 1
},
}, App))
.$mount('#root');
And bleow is my App component code
<template>
<div id="app" :data-id="test">
</div>
</template>
<script>
console.log(this.data);
</script>
assign variable var app = new Vue({..}) to your Vue App. and access variable outside vue app by using appname.variable_name like app.message
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
console.log(app.message);
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
{{ message }}
</div>

Vue instance inside Vue instance

Sup people!
I got this HTML code here:
// index.html
<div data-init="component-one">
<...>
<div data-init="component-two">
<button #click="doSomething($event)">
</div>
</div>
This basically references a Vue instance inside another Vue instance if I understood everything correctly. The respective JS code is split up in two files and looks like this:
// componentOne.js
new Vue(
el: '[data-init="component-one"]',
data: {...},
methods: {...}
);
// componentTwo.js
new Vue(
el: '[data-init="component-two"]'
data: {...}
methods: {
doSomething: function(event) {...}
}
);
Now, the problem with this is, that doSomething from componentTwo never gets called.
But when I do some inline stuff, like {{ 3 + 3 }}, it gets computed like it should. So Vue knows there is something. And it also removes the #click element on page load.
I tried fiddling around with inline-template as well, but it doesn't really work as I'd expect it to in this situation. And I figured it isn't meant for this case anyway, so I dropped it again.
What would the correct approach be here? And how can I make this work the easiest way possible with how it's set up right now?
The Vue version we use is 2.1.8.
Cheers!
The problem is that you have two vue instances nested to each other.
If the elements are nested, then you should use the same instance or try components
https://jsfiddle.net/p16y2g16/1/
// componentTwo.js
var item = Vue.component('item',({
name:'item',
template:'<button #click="doSomething($event)">{{ message2 }</button>',
data: function(){
return{
message2: 'ddddddddddd!'
}},
methods: {
doSomething: function(event) {alert('s')}
}
}));
var app = new Vue({
el: '[data-init="component-one"]',
data: {
message: 'Hello Vue!'
}
});
<div data-init="component-one">
<button >{{ message }}</button>
<item></item>
</div>
Separate instances work if they are independant of each other.
as follows:
https://jsfiddle.net/p16y2g16/
var app = new Vue({
el: '[data-init="component-one"]',
data: {
message: 'Hello Vue!'
}
});
// componentTwo.js
var ddd = new Vue({
el: '[data-init="component-two"]',
data: {
message: 'ddddddddddd!'
},
methods: {
doSomething: function(event) {alert('s')}
}
});
But when I do some inline stuff, like {{ 3 + 3 }}, it gets computed like it should. So Vue knows there is something.
Because you have parent instance 'componentOne'. It activated Vue for this template. If you need to set another instance inside, you have to separate part of template. Example (it can lag in snippet!) .
Alternative
https://jsfiddle.net/qh8a8ebg/2/
// componentOne.js
new Vue({
el: '[data-init="component-one"]',
data: {
text: 'first'
},
methods: {}
});
// componentTwo.js
new Vue({
el: '[data-init="component-two"]',
data: {
text: 'second'
},
template: `<button #click="doSomething($event)">{{text}}</button>`,
methods: {
doSomething: function(event) {
console.log(event);
}
}
});
<script src="https://vuejs.org/js/vue.min.js"></script>
<div data-init="component-one">
{{text}}
</div>
<div data-init="component-two">
</div>
The button element inside component-two is referenced as a slot in Vue.
The evaluation of the #click directive value happens in the parent component (component-one, which host component-two). Therefor, you need to declare the click handler over there (over component-one).
If you want the handler to be handled inside component-two, you should declare a click directive for the slot element in it's (component-two) template, and pass the handler function, for instance, as a pop.
good luck.
You're doing everything right except you've nested the 2nd Vue instance inside the 1st. Just put it to the side and it will work as expected.
Vue ignores binding more than once to the same element to avoid infinite loops, which is the only reason it doesn't work nested.
Use vue-cli to create a webpack starter app. vue init app --webpack
Then, try to structure your components this way. Read more: https://v2.vuejs.org/v2/guide/components.html#What-are-Components
This is main.js
import Vue from 'vue'
import ComponentOne from './ComponentOne.vue'
import ComponentTwo from './ComponentTwo.vue'
new Vue({
el: '#app',
template: '<App/>',
components: {
ComponentOne,
ComponentTwo
}
})
This is ComponentOne.vue
<template>
<div class="user">
<div v-for="user in users">
<p>Username: {{ user.username }}</p>
</div>
</div>
</template>
<script>
export default {
data () {
return {
users: [
{username: 'Bryan'},
{username: 'Gwen'},
{username: 'Gabriel'}
]
}
}
}
</script>
This is ComponentTwo.vue
<template>
<div class="two">
Hello World
</div>
</template>
<script>
export default {
}
</script>
<div th:if="${msg.replyFloor}">
<div class="msg-lists-item-left">
<span class="msg-left-edit"
th:classappend=" ${msg.unreadCount == 0} ? 'msg-all-read' ">您在</span>
<span th:text="${msg.topic.title}"
class="msg-left-edit-res"
th:classappend=" ${msg.unreadCount == 0} ? 'msg-all-read' ">问题回答</span>
<span th:text="${msg.type.name}"
class="msg-left-edit "
th:classappend=" ${msg.unreadCount == 0} ? 'msg-all-read' ">帖子相关</span>
<span class="msg-left-edit-number" >
产生了<span th:text="${msg.unreadCount} ? : ${msg.unreadCount} + '条新' : ${msg.unreadCount} + '条' "
th:class="${msg.unreadCount} ? : 'number-inner':''">2132条</span>回复
</span>
</div>
<div class="msg-lists-item-right">
<span th:text="${msg.lastShowTime}">2017-8-10</span>
</div>
</div>

VueJS - Component inside of v-for

I am trying to render a list of objects from my Vue-Instance. Each object should use a component, so I put the component into the v-for-loop. But all I get is list.title and list.text instead of the correct values.
Is there a special way to use components in v-for-loops?
I found this thread in the Vue-Forum, but don't know how to use it or if it's the right way.
App:
<div id="app">
<div v-for="list in lists">
<listcard title="list.title" text="list.text"></listcard>
</div>
</div>
Template:
<template id="listcard-template">
<div class="card">
<h2>{{ title }}</h2>
<p>{{ text }}</p>
</div>
</template>
My component:
Vue.component('listcard', {
template: '#listcard-template',
props: ['title', 'text']
})
Vue-Instance:
new Vue({
el: "#app",
data: {
lists: [
{title: "title1", text: "text1"},
{title: "title2", text: "text2"},
...
]
}
})
Thanks!
You should pass then as dynamic prop using : in front of parameters:
<listcard :title=list.title :text=list.text></listcard>
From documentation:
A common mistake beginners tend to make is attempting to pass down a number using the literal syntax:
<!-- this passes down a plain string "1" -->
<comp some-prop="1"></comp>
However, since this is a literal prop, its value is passed down as a plain string "1", instead of an actual number. If we want to pass down an actual JavaScript number, we need to use the dynamic syntax to make its value be evaluated as a JavaScript expression:
<!-- this passes down an actual number -->
<comp :some-prop="1"></comp>
https://vuejs.org/guide/components.html#Literal-vs-Dynamic

Vue js dynamically added property not reactive

I have a component which displays has a prop called obj. obj has two properties: obj.title and obj.body. Each is bound to a textfield so as to be reactive and editable.
<div id="app">
<controller :obj="{title: 'TITLE'}"></controller>
</div>
<template id="controller">
<input type="text" v-model="obj.title">
<p>{{ obj.title }}</p>
<input type="text" v-model="obj.body">
<p>{{ obj.body }}</p>
</template>
The title property is part of the prop which is bound to the component. But the body property has been added dynamically during the created callback. Here is the js:
Vue.component('controller', {
template: '#controller',
props: ['obj'],
created: function() {
this.obj.body = "BODY";
},
});
new Vue({
el: '#app',
});
The problem is that the body property isn't behaving reactively. Changes to the body textfield are not reflected by {{ obj.body }}.
The vue website has a section about Adding and Deleting Properties, but I couldn't get their suggestions to work.
Here is a jsfiddle demonstrating the problem.
Note: it has been suggested that I declare the body property at the same time as the title property. This would work, but for my use-case the property needs to be added dynamically.
Try to declare the body property when passing the prop:
<controller :obj="{title: 'TITLE', body: null}"></controller>
Or in your created method:
created: function() {
this.obj = {
title: this.obj.title,
body: 'some body
}
},
https://jsfiddle.net/crabbly/33721g9w/
I have selected this as the Accepted solution because it is what I would recommend to someone else with the same problem.
As user crabbly noticed, the reactivity can only be re-established if the prop's reference is updated.
I think the nicest way to do this is by making a shallow copy:
created: function() {
this.obj.body = 'BODY'
/**
* ... other code that adds other properties and messes around with obj...
*/
this.obj = Object.assign({}, this.obj);
}
... here, Object.assign is responsible for updating the reference.
This solution is currently not supported by IE, though any "clone" function will do (e.g. this.obj = jQuery.extend({}, this.obj); also works).

Categories