I'm using Laravel 5.3 with Vue.js(very new to this).
Here's my current code
app.js
var vm = new Vue({
el: '#app',
data: {
messages: []
},
ready: function(){
this.getMessages();
},
methods: {
getMessages: function(){
this.$http.get('api/messages').then((response) => {
this.$set('messages', data);
}, (response) => {
});
}
}
});
api.php route is very simple
Route::get('/messages', function() {
return Message::latest()->get();
});
Note: here when i try access the route directly as localhost:8000/api/messages i get the array with the full data
On my view i have
<div class="content" id="app">
<tr v-for="message in messages">
<td> #{{ message}} </td>
</tr>
</div>
I have included online libraries for all jquery, vue.js, and vue.resource.
When i use vue.js debugger it shows that it returns messages[] but it's empty.
I have followed a lot of examples but couldn't get it to work.
Any help is greatly appreciated
if you are using vue.js 2.0 , ready is deprecated now, you may use mounted instead
mounted: function () {
this.$nextTick(function () {
this.getMessages();
})
}
Vue.js Docs
Since you are using the arrow syntax, then I switched to full ES2015 Code
getMessages() {
this.$http.get('api/messages')
.then( result => {
this.messages = result.json()
})
}
Try this:
var vm = new Vue({
el: '#app',
data: {
messages: []
},
ready: function(){
this.getMessages();
},
methods: {
getMessages: function(){
let ctrl = this;
this.$http.get('api/messages').then((response) => {
this.messages = response.data;
});
}
}
});
Related
I wrote a small code with Laravel, Vue and JQuery, which works fine. Now I want to remove JQuery and run all with Vue and Axios.
Here's my template:
<ul id="product_list" class="vue-list-wrapper list-wrapper" data-rest="{{ route('rest_get_products', ["id"=>$product_type_id]) }}" data-pagination="0">
<li v-for="item in items">
<div class="item-name item-section">#{{ item.name }}</div>
...bla bla...
</li>
</ul>
Following code actually works and I can render what I get from AJAX. I know how to apply Axios, no problem.
The point I'm confused about: How can I ensure $(document).ready( functionality with Vue?
(function(){
"use strict";
function init_vue_list(){
var vue_list_handler = new Vue({
el: '.vue-list-wrapper',
data: {
items: []
},
mounted: function (event) {
var self = this;
var ajax_url = this.$el.getAttribute('data-rest');
$.ajax({ // No problem to convert this to Axios.
url: ajax_url,
method: 'GET',
success: function (data) {
self.items = data;
},
error: function (error) {
console.log(error);
}
});
},
methods:{
open_production:function(event){
}
}
});
}
$(document).ready( // I'm confused how I can replace this with Vue.
function(){
if($('.vue-list-wrapper').length > 0) {
init_vue_list();
}
}
);
})(document, $);
The recommended way by vue to do this is using mounted().
mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
Check: https://v2.vuejs.org/v2/api/#mounted
Similar approach, but without JQuery and just using Javascript:
mounted() {
document.addEventListener('DOMContentLoaded', function () {
// INSERT CODE HERE
});
}
You can do this inside mounted, assuming that you are using JQuery:
mounted() {
$(function() {
// Your code goes here...
})
}
I try to dynamic notify when I wrote some messages.
That's my vue.js code.
<script>
Vue.http.options.emulateJSON = true; // Send as
new Vue({
el: '#app',
data: {
name : "",
postResult : ""
},
methods: {
click: function() {
this.$http.post('/api/test', {name:this.name}).then(function(response){
var result = response.data;
//this.postResults.push(result.name);
if (result.name == "1234")
{
this.postResult = "<div> Success </div>";
}
else
{
this.postResult = "<div> Fail </div>";
}
}, function(response){
// Error Handling
});
}
}
});
</script>
When I use jQuery's Ajax, I used this method. But my vue.js script is not working. Should I study more about Vue JS? or I forget some syntax in this vue.js?
<template>
<div v-if='requestCompleted'>
<div v-if='!postResult'> Fail </div>
<div v-else-if='postResult'> Success </div>
</div>
</template>
<script>
Vue.http.options.emulateJSON = true; // Send as
new Vue({
el: '#app',
data: {
name : "",
postResult : null,
requestCompleted: false
},
methods: {
click: function() {
this.$http.post('/api/test', {name:this.name}).then((response)=>{
var result = response.data;
this.requestCompleted=true;
if (result.name == "1234")
{
this.postResult = true;
}
else
{
this.postResult = false;
}
}, function(response){
// Error Handling
});
}
}
});
</script>
Use arrow functions for getting access to 'this' inside your callback function.
For HTTP requests, it's better to use Axios. Also, you can use vuex store and manage your requests with actions
You don't have "this" inside your response callback. Do var me = this at the top level of your click function, then do me.postResult = ... in the callback.
In general terms, try and keep all your markup in the template element, no ?
Learning Vue and stuck. I have a brand new Laravel 5.4 project that I am using to learn Vue concepts, using Pusher/Echo. All is working in terms of message broadcasting, and the messages are fetched from the server and displayed on page load as expected. I want to programatically (from somewhere else in the project) send a message into the queue.
I am using this example as guide to accessing the Vue method outside the instance.
Why can I not access the instance method from my main JS file? The project is compiled with webpack FYI.
My Vue.js file:
$(document).ready(function()
{
Vue.component('chat-system', require('../components/chat-system.vue'));
var chatSystem = new Vue({
el: '#system-chat',
data: {
sysmessages: []
},
created() {
this.fetchMessages();
Echo.private(sys_channel)
.listen('SystemMessageSent', (e) => {
this.sysmessages.unshift({
sysmessage: e.message.message,
player: e.player
});
});
},
methods: {
fetchMessages() {
axios.get(sys_get_route)
.then(response => {
this.sysmessages = response.data;
});
},
addMessage(sysmessage) {
this.sysmessages.unshift(sysmessage);
this.$nextTick(() => {
this.$refs.sysmessages.scrollToTop();
});
axios.post(sys_send_route, sysmessage)
.then(response => {
console.log(response.data);
});
},
sendMessage(sysmessage) {
if (sysmessage !== '') {
this.$emit('systemmessagesent', {
player: this.player,
message: sysmessage
});
}
}
}
});
});
My Vue.js component:
<template>
<div id="round-status-message" class="round-status-message">
<div class="row">
<div class="col-xs-12" v-for="sysmessage in sysmessages">
{{ sysmessage.message }}
</div>
</div>
</div>
</template>
<script>
export default {
props: ['player', 'sysmessages'],
data() {
return {
newSysMessage: ''
}
},
methods: {
scrollToTop () {
this.$el.scrollTop = 0
},
sendMessage() {
this.$emit('systemmessagesent', {
player: this.player,
message: this.newSysMessage
});
this.newSysMessage = ''
}
}
};
</script>
I want to send a message into the queue programatically, so in my app.js, to test, I do:
// TESTING SYSTEM MESSAGES - DELETE
window.setInterval(function(){
var resp = {};
resp.data = {
id: 1,
message: "She hastily put down yet, before the end of half.",
progress_id: 1,
created_at: "2017-08-17 14:01:11",
updated_at: "2017-08-17 14:01:11"
};
chatSystem.$refs.sysmessages.sendMessage(resp);
console.log(resp);
}, 3000);
// TESTING SYSTEM MESSAGES - DELETE
But I get Uncaught ReferenceError: chatSystem is not defined
All I needed was to make the method name available to the global scope?
global.chatSystem = chatSystem; // App variable globally
This seems to work now...
Setup:
I have multiple Vue components, and each component has multiple instances in different dialogs in my web app.
For each type of component I have a global state (handrailOptions in the example below) so that each type of component stays in sync across the dialogs.
I'd like for it so that when a component proceeds beyond step 1, I hide the other components in that dialog.
I have achieved this nicely using the computed / watch combo.
However, my problem is that it seems if I try to listen in with computed through more than 1 Vue instance, it hijacks the other listeners.
Problem
Below is a simplified version of what I'm working with, when the app starts up, the console logs 'computed 1' & 'computed 2'. But then when I change handrailOptions.step, only the second fires. ('computed 2' & 'watched 2')
Is there any way to have multiple Vues have a computed listener working on the same value?
handrailOptions = {
step: 1
};
Vue.component( 'handrail-options', {
template: '#module-handrail-options',
data: function() {
return handrailOptions;
},
});
var checkoutDialog = new Vue({
el: '#dialog-checkout',
computed: {
newHandrailStep() {
console.log('computed 1');
return handrailOptions.step;
}
},
watch: {
newHandrailStep( test ) {
console.log('watched 1');
}
}
});
new Vue({
el: '#dialog-estimate-questions',
computed: {
newHandrailStep() {
console.log('computed 2');
return handrailOptions.step;
}
},
watch: {
newHandrailStep( test ) {
console.log('watched 2');
}
}
});
This works as expected. I made handrailOptions responsive by making the data object of a new Vue. Making it the data object of a component, as you did, could also work, but the component would have to be instantiated at least once. It makes more sense to have a single object for your global, anyway.
handrailOptions = {
step: 1
};
// Make it responsive
new Vue({data: handrailOptions});
var checkoutDialog = new Vue({
el: '#dialog-checkout',
computed: {
newHandrailStep() {
console.log('computed 1', handrailOptions.step);
return handrailOptions.step;
}
},
watch: {
newHandrailStep(test) {
console.log('watched 1');
}
}
});
new Vue({
el: '#dialog-estimate-questions',
computed: {
newHandrailStep() {
console.log('computed 2', handrailOptions.step);
return handrailOptions.step;
}
},
watch: {
newHandrailStep(test) {
console.log('watched 2');
}
}
});
setInterval(() => ++handrailOptions.step, 1500);
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="dialog-estimate-questions">
Main step {{newHandrailStep}}
</div>
<div id="dialog-checkout">
CD step {{newHandrailStep}}
</div>
Im grabbing this JSON object and passing it on to this Vue. However, It is not updating on my page, but the object is there since window.alert(jobj.Name) works fine. Here is my vue and my view.
var app2 = new Vue({
el: '#menuPage',
data: {
HeaderTitle: 'NOT CHANGED',
content_body: 'test body',
},
methods: {
loadMENU: function (jobj) {
app2 = this;
window.location.href = "tools/menu.html"; //relative to domain
window.alert(jobj.Name);
this.HeaderTitle = jobj.Name;
}
} });
<div id="menuPage">{{HeaderTitle}}</div>
It is only showing "NOT CHANGED" Instead of the object Name.
You didn't call the method. You should use a button to trigger the method.
html
<div id="menuPage">{{HeaderTitle}}
<button v-on:click="loadMENU">button</button>
</div>
javascript
var app2 = new Vue({
el: '#menuPage',
data: {
HeaderTitle: 'NOT CHANGED',
content_body: 'test body',
},
methods: {
loadMENU: function () {
app2 = this;
const herf = window.location.href;
window.alert(herf);
this.HeaderTitle = herf;
}
} });