Functionality like $(document).ready( with Vue.js - javascript

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...
})
}

Related

Inserting dynamic html tags using Vue.js

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 ?

How does react.js know that data has changed?

Using React.js I have written a simple app that gets json and uses some of that data returned to build html.
Although, when the JSON changes, the html does not. Am I missing something here?
Here is my code -
<script type="text/jsx">
var classNames = ({
'auditNumber': "auditNumber",
'audit-overview-box': "audit-overview-box"
});
var AuditOverviewBox = React.createClass({
render: function () {
return (
<div className="audit-overview-box">
<h1 className={classNames.auditNumber}>{this.props.auditNo}</h1>
<span>{this.props.creationDate}</span>
</div>
)
}
});
var AuditBoxes = React.createClass({
getInitialState: function () {
return {
data: []
}
},
componentWillMount: function () {
this.dataSource();
},
componentWillReceiveProps: function (nextProps) {
this.state.data(nextProps);
},
dataSource: function (props) {
props = props || this.props;
return $.ajax({
url: '../json.php',
dataType: 'json',
cache: false,
success: function (data) {
this.setState({data: data});
}.bind(this),
error: function (xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
render: function () {
var data = this.state.data;
console.log("data");
var photos = data.map(function (audit) {
return <AuditOverviewBox key={audit.auditNo.toString()} auditNo={audit.auditNo}
creationDate={audit.creationDate}/>
});
return (
<div className='myAudits'>
{photos}
</div>
)
}
});
ReactDOM.render(<AuditBoxes />, document.getElementById('audits-div'));
</script>
And the JSON -
[{
"auditNo": "a1201",
"creationDate": "21/10/2016"
},
{
"auditNo": "a1221",
"creationDate": "21/10/2016"
},
{
"auditNo": "a1211",
"creationDate": "21/10/2016"
}]
You cannot push changes from the server to the browser (unless you use websockets). If you just need to update once in a while you should setup your code around the ajax request in such a way that it will perform a request every n seconds. The simplest solution would be using setInterval()
setInterval(
function () {
// your ajax code
},
5000
)
that way the request to the server will be done every 5 seconds. Please be aware that you can overload your server if you set the interval to short / have a lot of visitors.
There are only two ways to change the data. You can use .setState method or directly set data to .state property and call .forceUpdate method of component, but this method is stritly unrecommended.
You can read more about it here: https://facebook.github.io/react/docs/state-and-lifecycle.html

Vue.js with laravel 5.3

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;
});
}
}
});

Throwing "unexpected token" error, when i use jsop api in reactjs?

When i used to fetch data from json api its throwing "Unexpected token" error. Below, i've added my code what i have tried so far. Get me out from this issue. I'm trying to solve this problem long time.
Here,
var Demo = React.createClass({
render: function() {
getInitialState:function(){
return {
data:[]
};
},
componentDidMount: function () {
$.ajax({
url: "http://www.w3schools.com/angular/customers.php"
}).done(function(data) {
this.setState({data: data})
});
},
return (
<div>
{this.props.data.map(function(el,i) {
return <div key={i}>
<div>{el.Name}</div>
<div>{el.City}</div>
<div>{el.Country}</div>
</div>;
}
</div>
);
}
});
var Stream = React.createClass({
render: function() {
return (
<div>
<div className="scrollContent ">
<Demo />
</div>
</div>
);
}
});
You have several errors in your code
move getInitialState and componentDidMount from render method, these methods should be as children of your component (Demo) class but not as children of render method
add dataType: 'json' to $.ajax, because now it returns string, but in your case you need get json
as you are using this.setState in .done you should set this to .done callback, because now this refers to $.ajax object not Demo, you can use .bind method to do it.
change this.props.data to this.state.data because data located in state object not in props
array with data located in records property use it instead of just data
Example
var Demo = React.createClass({
getInitialState:function() {
return {
data :[]
};
},
componentDidMount: function () {
$.ajax({
url: "http://www.w3schools.com/angular/customers.php",
dataType: 'json'
}).done(function(response) {
this.setState({ data: response.records });
}.bind(this));
},
render: function() {
var customers = this.state.data.map(function(el,i) {
return <div key={i}>
<div>{el.Name}</div>
<div>{el.City}</div>
<div>{el.Country}</div>
</div>
});
return <div>{ customers }</div>;
}
});

Marionette best way to do self render

Hello here is my little code :
i don't know how to make this more marionette ... the save function is too much like backbone...
self.model.save(null, {
success: function(){
self.render();
var vFormSuccess = new VFormSuccess();
this.$(".return").html(vFormSuccess.render().$el);
}
var VFormSuccess = Marionette.ItemView.extend({
template: "#form-success"
} );
http://jsfiddle.net/Yazpj/724/
I would be using events to show your success view, as well as using a layout to show your success view, if it's going into a different location.
MyLayout = Marionette.Layout.extend({
template: "#layout-template",
regions: {
form: ".form",
notification: ".return"
}
initialize: function () {
this.listenTo(this.model,'sync',this.showSuccess);
this.form.show(new FormView({model: this.model}));
},
showSuccess: function () {
this.notification.show(new VFormSuccess());
}
});
Or, you could do the same with just the one region, and having the FormView be the layout itself. You just need to ensure there is an element matching the notification region exists in the layout-template.
MyLayout = Marionette.Layout.extend({
template: "#layout-template",
regions: {
notification: ".return"
}
initialize: function () {
this.listenTo(this.model,'sync',this.showSuccess);
},
showSuccess: function () {
this.notification.show(new VFormSuccess());
}
});
What this allows you to do:
You can then show an error view quite easily, if you wanted. You could replace initialize with
initialize: function () {
this.listenTo(this.model,'sync',this.showSuccess);
this.listenTo(this.model,'error',this.showError);
},
and then add the following, ensuring you create a VFormError view.
showError: function () {
this.notification.show(new VFormError());
}
You should be able to write
self.model.save(null, {
success: function(){
self.render();
}
...
Why are you doing this
this.$(".return").html(vFormSuccess.render().$el);
If you define that template as the view template you could simply refer to it with $el, if you need two different templates then you might think about using a Controller, to decide what to use and who to use it.
If you use Marionette, you don't call render directly but instead use Marionette.Region to show your views.

Categories