I'm currently trying to wrap my head around how to extend a vuejs instance. Specifically I want to separate an instance, so that I can reuse the base of an instance (the element and the data). I currently have different (laravel/blade) views for adding and editing items (domains), and I want to share a vuejs instance between these two, but I don't want to have the same code (the base) in two places.
Basically, what I'm searching for is the following:
<script type="text/javascript">
var vue = new Vue({
el: '#domain',
data: {
form: {
'name' : '',
'git_repo' : '',
'auto_deploy' : '',
'create_db' : ''
},
ajaxResponse : ''
}
});
</script>
<script type="text/javascript">
Vue.extend('domain_methods', {
methods: {
postDomain: function () {
this.$http.post('{{ route('domain.store') }}', function (data, status, request) {
this.$set('ajaxResponse', data);
}, {
data: this.form
} ).error(function (data, status, request) {
this.$set('ajaxResponse', data);
});
}
}
});
</script>
But that obviously doesn't work. I just want to use the postDomain() method within the #domain element, without the method being written in the initial creation of the instance.
Thanks in advance!
Be careful – you are conflating the usage of .extend() with that of .component(). They do very different things. This section of the docs has more information on the differences:
http://vuejs.org/guide/components.html
In this particular case, just declare your top level Vue class via .extend() and then instantiate a subclass of it by using it as a constructor. This gives you inheritance-like behavior.
So, for instance:
<script type="text/javascript">
var MainVue = Vue.extend({
data: function () {
return {
form: {
'name' : '',
'git_repo' : '',
'auto_deploy' : '',
'create_db' : ''
},
ajaxResponse : ''
};
}
});
</script>
<script type="text/javascript">
var secondary_vue = new MainVue({
el: '#domain',
methods: {
postDomain: function () {
this.$http.post('{{ route('domain.store') }}', function (data, status, request) {
this.$set('ajaxResponse', data);
}, {
data: this.form
} ).error(function (data, status, request) {
this.$set('ajaxResponse', data);
});
}
}
});
</script>
Related
I have a reusable Vue component as follows:
Vue.component('ValueDisplay', {
template: '<div v-html="value"></div>',
data: function () {
value: ''
},
mounted: function() {
this.$el.client = this;
},
methods: {
SetValue: function(value) {
this.value = value;
},
}
});
It is intended to be used as follows:
<value-display id="battery_percent">
Code that processes data from a web socket then calls the following function to set the value.
window.SetValue = function(name, value)
{
var el = document.getElementById(name);
if ((null != el) && el.hasOwnProperty('client')) {
el.client.SetValue(value);
}
}
This allows me to separate the display code and the web socket handling code as the web socket handling code is re-used for multiple HTML pages. I have used a similar pattern with a lot of success in my code, but this is failing.
The value is not being displayed and the web console is displaying the following error:
ReferenceError: value is not defined
Experimentation shows that this is because Vue thinks that there is no variable called "value" within the "data" part of the component.
Elsewhere I have another Vue component that is more complex. It has multiple values that are used, and updated, in a similar fashion. It works fine.
Vue.component('NavPane', {
template: `<table class="fixed">
...
<td v-html="speed"></td>
...
data: function () {
return {
...
speed: ''
}
},
mounted: function() {
},
methods: {
}
});
When you boil it down, this code is doing exactly the same thing as the failing code, but this component works.
You've got a small mistake here:
data: function () {
value: ''
},
You've merged the braces from a function declaration and an object literal. It should be something like this:
data: function () {
return {
value: ''
}
},
We are building a web application using Vue JS and PHP, we are new to Vue JS. The server-side execution is fine, the API is able to fetch data as JSON. While trying out a static array display before making the API call, we find that the function in imported "app.js" is not getting called and the table displayed is empty. Please let us know what we might be doing wrong. Appreciate your help.
import Vue from 'vue';
export const MY_CONST = 'Vue.js';
export let memberList = new Vue({
el: '#members',
data: {
members: []
},
mounted: function () {
this.getAllMembers();
},
methods: {
getAllMembers: function () {
/*
axios.get("https://xxxxxx.com/services/api.php")
.then(function (response) {
memberList.members = response.data.members;
});
*/
memberList.members = [{ "empname": "Dinesh Dassss" },
{ "empname": "Kapil Koranne" }];
}
}
});
This is the Vue component. The members object is empty.
<script>
import * as mykey from './app.js'
export default {
name: 'Home',
props: {
msg: String
},
data() {
return {
message: `Hello ${mykey.MY_CONST}!`,
members: mykey.memberList.members
}
}
};
</script>
You can also use this reference for current instance reference:
getAllMembers: function () {
var me = this;
/*
axios.get("https://xxxxxx.com/services/api.php")
.then(function (response) {
// direct this not works here but we have
//saved this in another variable and scope of a var is there
me.members = response.data.members;
});
*/
// this reference works fine here.
this.members = [{ "empname": "Dinesh Dassss" },
{ "empname": "Kapil Koranne" }];
}
I am using Vue2. I am getting json data via ajax in my mounted method. I then set that data to a data variable expecting to be able to access it from other methods outside of mounted, but all I get is an empty observable.
Any suggestions/advice? Thanks for the help.
var vm = new Vue({
el: '#app',
data: function () {
return {
allJson: []
};
},
methods: {
updateTableData: function(isActive) {
// cannot access this.allJson here
}
},
mounted: function() {
$.getJSON(Routes.USERS_GET_JSON, function(json) {
this.allJson = json;
});
}
});
I haven't used jQuery in a long, long time, but if I remember correctly you need to explicitly declare the context of this if you wish to use it within the callback, else you get something unexpected. However, I don't know if $.getJSON supports it even though it's a wrapper. So you can try the following:
$.getJSON(Routes.USERS_GET_JSON, function(json) {
this.allJson = json;
}, {
context: this
})
Or you can use .bind off of the function to scope this
$.getJSON(Routes.USERS_GET_JSON, function(json) {
this.allJson = json
}.bind(this))
Or if you're tranpsiling down with babel (which you probably are) you can use fat arrow syntax:
$.getJSON(Routes.USERS_GET_JSON)
.done( (json) => {
this.allJson = json
})
Or you can just alias this before the $.getJSON
let _self = this
$.getJSON(Routes.USERS_GET_JSON, function(json) {
_self.allJson = json
})
My guess is that this is not bound to your vue instance inside the callback function. Try the following
var vm = new Vue({
el: '#app',
data: function () {
return {
allJson: []
};
},
methods: {
updateTableData: function(isActive) {
// cannot access this.allJson here
}
},
mounted: function() {
const self = this;
$.getJSON(Routes.USERS_GET_JSON, function(json) {
self.allJson = json;
});
}
});
So,I'm giving me first proper look at Vue.js since 2.0. And I'm having a hard time going from filter to computed.
Here is where I'm at (using vue-resource for the API call):
var moviesURL = 'http://localhost/api/movies';
var app = new Vue({
el: '#app',
data: {
liveFilter: '',
movies: ''
},
methods: {
getMovies: function() {
this.$http.get(moviesURL).then(response => {
this.movies = response.body;
}, response => {
console.log(response);
});
}
},
computed: {
filteredMovies: function() {
var self = this
return this.movies.filter(function(movie) {
return movie.indexOf(self.liveFilter) !== -1
});
}
},
created: function() {
this.getMovies();
}
});
And I keep getting those errors:
And I can't really my finger on what I'm doing wrong... Any idea?
You cannot filter over string. In your data movies should be an empty array, not empty string.
Also, be sure that response.body is an array too.
You initiate the movies as an empty string, and a string doesn't have a .find() method. Use an empty array instead
How to structure multiple pages with RequireJS? Is, like the following sample, declaring every class in app.js is the right thing to do? Has every html file to declare the <script data-main="src/main" src="src/require.js"></script>?
What I want to avoid is loading all the script when a user reach the first page of a site.
main.js defining all external dependencies:
require(
{
baseUrl:'/src'
},
[
"require",
"order!http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js",
"order!http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js",
"order!http://ajax.cdnjs.com/ajax/libs/underscore.js/1.1.6/underscore-min.js",
"order!http://ajax.cdnjs.com/ajax/libs/backbone.js/0.3.3/backbone-min.js"
],
function (require) {
require(["app"], function (app) {
app.start();
});
}
);
app.js file defining every component:
define([ "product/ProductSearchView",
"product/ProductCollection"
], function (ProductSearchView,
ProductCollection) {
return {
start: function() {
var products = new ProductCollection();
var searchView = new ProductSearchView({ collection: products });
products.fetch();
return {};
}
}
});
You can require files within your existing module. So say when someone clicks a link you could trigger a function that does the following:
// If you have a require in your other module
// The other module will execute its own logic
require(["module/one"], function(One) {
$("a").click(function() {
require(["new/module"]);
});
});
// If you have a define in your other module
// You will need to add the variable to the require
// so you can access its methods and properties
require(["module/one"], function(One) {
$("a").click(function() {
require(["new/module"], function(NewModule) {
NewModule.doSomething();
});
});
});
This is a complete example of how this all works; require.js and order.js are in the same directory as the app's JS files.
<html>
<head>
<script data-main="js/test" src="js/require.js"></script>
</head>
<body>
<button>Clickme</button>
</body>
</html>
test.js (in js folder)
require(
{
baseUrl:'/js'
},
[
"order!//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js",
"order!//ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js"
],
function () {
require(["app"], function (app) {
app.start();
});
}
);
app.js (in js folder) with a on-demand load of Employee.js:
define([], function () {
return {
start: function() {
$('button').button();
$('button').click(function() {
require(['Employee'], function(Employee) {
var john = new Employee('John', 'Smith');
console.log(john);
john.wep();
});
});
return {};
}
}
});
Employee.js (in js folder):
define('Employee', function () {
return function Employee(first, last) {
this.first = first;
this.last = last;
this.wep = function() {
console.log('wee');
}
};
});