In a Laravel blade template I can access some data using #{{list.length}}.
<template id="events-template">
#{{list.length}}
</template>
How do I use this within a javascript function within the same view template?
Vue is defined in app.js as
var vm = new Vue({
el: 'body',
});
app.js is called before the script in my view template
First, be sure that you actually have defined the list var in your vue instance
data: {
list: []
}
Then, to access the list var, use the instance scope, for example in some method
methods: {
someMethod: function () {
console.log(list) // undefined
console.log(this.list) // []
}
}
Related
I'm using Vue to build an app with Esri's Mapping API.
Via the Esri API, I'm able to set a popup template content using an object:
const popupWindowTemplate = {
title: "{mag} magnitude near {place}",
content: getContent
};
and a function
getContent: function(){
let node = document.createElement('div');
node.innerHTML = "<button type='button'>Do my thing!</button>"
return node;
}
However, I would like the getTemplate function to return a Vue component rendered in the innerHTML instead of hard coded html.
I have a component:
const buffer = Vue.component('do-mything', {
template: '<div><button type="button" #click="domything">Do my thing!</button></div>',
data() {
return {
somevalue: ''
};
}
});
and suspect it has something to do with components render functions, but have been having trouble figuring out how to insert the component in the getContent function.
Assuming the that API, you integrate with, expects getContent method to return a DOM element, you can try to:
create a component instance
render it off-document (by calling $mount without args on the component instance)
return the DOM element the component was rendered to
To implement the above getContent method may look like as follows:
getContent: function(){
const vueComponent = new Vue({
template: '<div><button type="button" #click="domything">Do my thing!</button></div>',
methods: {
domything() {
console.log('Method was called')
}
}
});
return vueComponent.$mount().$el;
}
I have a simple vue component with one method that I am trying to call outside of it's wrapper element #app but it is not triggering. Is there a way to reigster the view component so that I could call it with Component.function();
var viewModel = new Vue({
el: "#app",
data: {},
methods: {
test: function() {
alert("test fuction called");
}
}
});
HTML:
<div id="app">
</div>
<a #click="viewModel.test()">Click me!</a>
Fiddle:
https://jsfiddle.net/queeeeenz/Lja7pake/198/
I tested for a while.
It might be not able to use # in elements outside of Vue element
The var viewModel seems not attached to window object
I can run with this though
JS
window.viewModel = new Vue({
el: "#app",
data: {},
methods: {
test: function() {
alert("test fuction called");
}
}
});
HTML
<div id="app">
</div>
<a onClick="viewModel.test()">Click me!</a>
First of all, it seems like you are attaching a click handler the "Vue" way, without actually it being a Vue component. That is not going to work.
To strictly achieve what you want, you have to expose your function to a different scope, e.g. via assigning it to a window attribute.
var viewModel = new Vue({
el: "#app",
data: {},
created () {
// Now it is exposed
window.test = this.test;
},
methods: {
test: function() {
alert("test fuction called");
}
}
});
// And later
window.test();
A better way of doing this is probably by using a global event bus. Instead of exposing random functions in the global scope, you can instead create a bus that you expose instead. The nice part about that is that if everything happens within the Vue application, you could use this.$bus.$emit('...') from anywhere in the Vue application and listen to it everywhere else in the Vue application. The nice part if it is used outside the Vue application is that you use a set interface between the inside of your Vue application and the outside of your Vue application, preventing you from having to expose more and more functions in the global scope, and allowing you to figure out what can and cannot be done from outside the Vue application.
import Vue from 'vue';
export const bus = new Vue();
// Elsewhere
import { bus } from './bus';
Vue.prototype.$bus = bus;
// In outside code
import { bus } from '../../my-vue-application/bus';
bus.$emit('test');
// In your component
var viewModel = new Vue({
el: "#app",
data: {},
created () {
this.$bus.$on('test', this.test);
},
beforeDestroy () {
this.$bus.$off('test', this.test);
},
methods: {
test: function() {
alert("test fuction called");
}
}
});
I am trying to get data from json file, it has just json data.
[{"id":81,"body":"There are some reason to fix the issues","created_at":"2017-11-16 11:56:47","updated_at":"2017-11-16 11:56:47"}]
I added vue-resource and properly use it as per vue syntax.
import vueResource from 'vue-resource'
Vue.use(vueResource)
In my userlist component i am trying following script
export default {
data:function(){
return {
list:[],
car:{
id:'',
body:''
}
};
},
created: function(){
this.fetchCarList();
},
methods:{
fetchCarList: function(){
this.$http.get('http://localhost:8080/api.js').then(function(response){
this.list = response.data
});
}
}
}
And this is component HTML loop
<ul id="example-1">
<li v-for="item in list">
{{ item.body }}
</li>
</ul>
I have checked http://localhost:8080/api.js which is properly returning the data. Also when I am adding the json data in fetchCarList method then loop works fine but with get() call it does not working.
How can I solve the issue?
You have a scoping issue: this within the callback does not refer to your Vue instance. That is because you are not using ES6 arrow function, i.e.:
this.$http.get('http://localhost:8080/api.js').then(response => {
this.list = response.data
});
...which means the outer this is not passed in. You will have to proxy that yourself, i.e. var self = this on the outside, and then use self.list = response.data:
var self = this;
this.$http.get('http://localhost:8080/api.js').then(response => {
self.list = response.data
});
I have a simple Vue instance and want to pass json from the backend to vue without HTTP request because it's always the same.
I've tried do this with props, but it doesn't work...
In DOM it's looks like <div id="my-component" prices="[object Object]">
Vue debug tool show me image as an empty string, and in console undefined
<div id="my-component" :prices="{{ $prices }}">
</div>
<script>
new Vue({
el: '#my-component',
props: ['prices'],
mounted: function() {
console.log(this.image);
},
});
</script>
where $prices json encoded array.
Your solution was nearly there but you don't need a prop, rather use a data attribute and assign the JSON via a method:
new Vue({
el: '#app',
data: {
json: {},
},
methods: {
setJson (payload) {
this.json = payload
},
}
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app" :json="setJson({ foo: 'bar' })">
<pre>{{ json }}</pre>
</div>
You would just assign your Laravel data to the setJson methods payload, i.e.
:json="setJson({{ $prices }})
I don't know if there is any Laravel helper for this but I will present a generic approach.
One option would be to store you JSON data in a global variable and the page loads and then use it in your js files.
Basically you need to generate some html similar to:
<script>
window.myApp = window.myApp || {};
window.myApp.userData = { "firstName": "John", "lastName": "Doe" };
</script>
Then from javascript you should be able to access the myApp.userData variable and use it when initializing the Vue component.
new Vue({
el: '#app',
data: {
userData: myApp.userData
}
});
Here is an example:
new Vue({
el: '#app',
data: {
userData: myApp.userData
}
});
<script>
window.myApp = window.myApp || {};
window.myApp.userData = { "firstName": "John", "lastName": "Doe" };
</script>
<div id="app">
Hello {{userData.firstName}}
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
I have upvoted this answer first, but I have to change my vote (can't do it actually not enough reputation...).
Please do not set the data this way, because it will trigger an error like this:
[Vue warn]: You may have an infinite update loop in a component render function
If anything will use the data you set this way (watch, render components based on it) you will have an infinite loop.
When you use this method:
you set the data in the render function (in the template)
if something triggers a re-render, the data will be set again
anything using this data will have to re-render, which may cause a
re-render on the main vue instance
This will cause the infinite loop.
LinusBorg have an explanation here.
While this op is old, here is how I would do it (inspired by how I do it in Symfony 4 + VueJS):
<div id="my-component" prices-data="{{ json($prices) }}">
</div>
<script>
new Vue({
el: '#my-component',
props: ['pricesData'],
data: {
prices: null,
},
mounted: function() {
this.prices = JSON.parse(this.pricesData);
},
});
</script>
This is obviously assuming that $prices is a blade variable.
Note: I used #json() above when $prices is a simple object that can be encoded with json_encode() (underlying function being used when you call blade json function. If however the object is complex, consider using JMS Serializer with #MaxDepth annotations if objects become too complex.
In a project with vue.js 2:
I've a component living in a .vue file that represents a list of elements. Also, I've a sidebar that is the summary of this list. This sidebar is another component in a .vue file.
So, how I can keep communication between each them, for example, if I removed a element from a list, reflect the change in a var declared in sidebar that is the total number of elements?To ilustrate:
SideBar.vue
<template>
...
<span></span> ===> here I need total of elements listed in ListElements.vue
...
<template>
ListElements.vue
<template>
...
#click="deleteEntry"
...
<template>
<script>
methods: {
deleteEntry(entry) {
//here I need to notify to SideBar.vue in order to update the total of elements in the this.entries list.
let index = this.entries.indexOf(entry);
if (window.confirm('Are you sure you want to delete this time entry?')) {
this.entries.splice(index, 1);
}
}
</script>
OK, I've created a simplified example of how this works. Your bus needs to be global so it is accessible by all Vue components, this simply means placing it outside of all other components and view models:
var bus = new Vue({});
var vm = new Vue({
// Main view model has access to bus
el: '#app'
});
Then you just need to emit the event on the bus on some event and catch that in the other component:
Component one emits a message to the bus on keyup:
Vue.component('component-one', {
template: '<div>Enter a message: <input v-model="msg" v-on:keyup="updateMessage"> </div>',
methods: {
updateMessage() {
bus.$emit('msg', this.msg);
}
},
data() {
return {
msg: ""
}
}
});
Component-two listens for the message:
Vue.component('component-two', {
template: "<div><b>Component one says: {{ msg }}</b></div>",
created() {
bus.$on('msg', (msg) => {
this.msg = msg;
});
},
data() {
return {
msg: ""
}
}
});
Here's the fiddle: https://jsfiddle.net/v7o6d2vL/
For your single page components to get access the the bus you just need to make sure your bus is in the global scope, which you can do by using window:
window.bus = new Vue({});
you can then use bus.$emit() and bus.$on() inside your components as normal