I have created a mixins file called as urlMixin.js as show below,
module.exports = {
data() {
return {
url: 'http://localhost:3000'
};
}
}
I have a component called as profile.vue in which I have imported the mixin file. The profile.vue file looks like this,
import axios from 'axios';
import urlMixin from './../../mixins/urlMixin';
export default{
data() {
return{
}
},
created: function(){
},
mixins : [ urlMixin ],
methods:{
getInfo: function(){
axios.get('this.url/profile')
.then(response =>{
})
.catch(e => {
this.errors.push(e);
})
}
}
}
I want to be able to replace the url value in the Profile.vue with the url value present in urlMixin.js file, like how it is shown in the profile.vue file. Is there a way using which I can achieve this?
If you are using ES6 you can use Template Literals to insert the value into the string:
axios.get(`${this.url}/profile`)
Or using plain Javascript:
axios.get(this.url + '/profile')
Related
I made a fake api call to my json file with axios. I get a promise back from the function where i can get my data from. but i don't want that. I want to receive the data from the function.
my code now: products.js
export default {
getAllProducts(axios) {
return axios.get('fakedb.json').then(response => {
return response.data;
});
}
}
the view file: a product.vue file
import productController from '~/data/controllers/product';
export default {
data() {
return {
products: productController.getAllProducts(this.$axios).then(res => this.products = res)
}
},
}
but this is not what i want to achieve.
what i want to achieve is this code in my product.vue file:
import productController from '~/data/controllers/product';
export default {
data() {
return {
products: productController.getAllProducts(this.$axios)
}
},
}
i want to receive the data without having to handle the promise in the view file. any solution how to return my data in the products.js file?
if i do a normal return from the products.js file like this it works fine:
export default {
getAllProducts(axios) {
return [
{
"name": "Product1",
"price": 9.75
},
{
"name": "Product2",
"price": 10.75
}
]
}
}
But i want it to go with axios
Since you have a .vue-file, I assume that this is a single-page vue component, right? And therefore you use vue-cli or webpack. I therefore assume that you can use async/await syntax.
Retrieving data from axios is asynchronous, because you basically cannot know how long it takes for it to retrieve the data over the network. And this kind of situation is what async/await is for.
So make the functions async:
products.js
export default {
async getAllProducts(axios) {
const response = await axios.get('fakedb.json');
return response.data;
}
}
product.vue:
import productController from '~/data/controllers/product';
export default {
data() {
return {
products: [],
};
},
async mounted: {
this.products = await productController.getAllProducts(this.$axios);
}
}
I do not think you can make the data function asynchronous, so return an empty data object (I have assumed that it is an array), and then use the mounted hook to retrieve data.
You can't. A function returns immediately and there is nothing meaningful for it to return if you don't want a promise, since loading won't have begun yet. This is the problem that promises solve to begin with. It's a bad pattern to make an async call into your data to begin with, though. Use this pattern instead:
data() {
return {
products: null
}
},
methods: {
getAllProducts() {
return axios.get('fakedb.json').then(response => {
this.products = response.data;
});
}
},
created() {
this.getAllProducts();
}
The async call is abstracted out into the created hook, and when it's resolved it will set the data accordingly.
Here's a little demo
I want to load a JSON file into my mithrilJs app before its startup and want to save this data in some global variable (JSON file is for some run time configuration of mithril application just like app_initializer in Angular)
so far I have done this in my app
import m from 'mithril';
import { a } from './MainView';
var Data = {
fetch: function() {
m.request({
method: "GET",
url: "./client/config/config.json",
})
.then(function(items) {
console.log(items)
// want to store this
m.route(document.body, "/accounts", a)
})
}
}
Data.fetch()
and my Main view file contains
import m from 'mithril';
import {Layout} from "./components/layout";
import {Accounts} from "./components/accounts";
import {AccountNew} from './components/newAccount';
export const a={
"/accounts": {
render: function (vnode) {
return m(Layout, m(Accounts))
}
},
"/accountsNew": {
render: function (vnode) {
return m(Layout, m(AccountNew))
}
},
}
so what could be better approach for this and also I want to store fetched json file data (items) in some global variable like props in react or services in angular , How I can do that to access everywhere in my app
The docs state that you can use onmatch to preload data, here is a rough translation of their example:
var state = {
items: null,
loadItems: function() {
if (state.items === null) {
return m.request("./client/config/config.json").then(function(items) {
state.items = items;
});
}
}
};
const a = {
"/accounts": {
onmatch: state.loadItems,
render: function (vnode) {
return m(Layout, m(Accounts))
}
},
"/accountsNew": {
onmatch: state.loadItems,
render: function (vnode) {
return m(Layout, m(AccountNew))
}
},
}
You can read their two examples in the documentation here: Preloading data.
Alternative solutions
These solutions don't really involve mithril because your are really loading the data before mithril is even used. You should be able to pass your state variable into the component as an attribute, ie. return m(Layout, m(Accounts, {state}));
Dumping JSON String into server side template
If you control the server side as well you can just dump your configuration directly into a global variable by outputting an escaped JSON string assigned to a javascript variable in your base template. I do this to dump model information or session information so my client side code can use it.
<script> var config = ${escapedJSONStringInServerVariable};</script>
Import config directly
You can also just import the configuration directly into your app if you rewrite your config.json to just export your configuration as an object.
import {Config} from ./client/config/config.js
Call m.request directly
Finally you can also just assign the promise returned from m.request to a var and return that promise in loadItems. This should fire m.request immediately but prevent the loading of your templates until the promise is resolved.
var state = (function () {
var configRequest = m.request({
url: "./client/config/config.json"
}).then(function(items) {
state.items = items;
});
return {
items: null,
loadItems: function() {
return configRequest;
}
};
})();
Try to save it in sessionStorage and check it after every reload.
if(!sessionStorage.key('myJson'))
sessionStorage.setItem('myJson','myJson')
This is the structure of my project (create-react-app):
Contents of /src/api/searchAPI.js:
import client from './client';
async function searchMulti(query, options = {}) {
options.query = query;
return await client.get('/search/multi', options);
}
export default {
searchMulti
};
Contents of /src/api/index.js:
import movieAPI from './movieAPI';
import personAPI from './personAPI';
import searchAPI from './searchAPI';
import configurationAPI from './configurationAPI';
export { movieAPI, personAPI, searchAPI, configurationAPI };
QuickSearch component imports searchAPI ands uses it to fetch some data over the web.
Now, I need to test (with react-testing-library) the QuickSearch component.
So, I would like to mock the api module (exported in /src/api/index.js) in order to use a mock function instead of searchAPI.searchMulti( ).
If I put below code in /src/componentns/__tests__/QuickSearch.js, it works just fine:
...
import { searchAPI } from '../../
...
...
jest.mock('../../api', () => {
return {
searchAPI: {
searchMulti: jest.fn().mockResolvedValue({ results: [] })
}
};
});
...
it('some test', () => {
searchAPI.searchMulti.mockResolvedValueOnce({ results: [] });
const { queryByTitle, getByPlaceholderText } = renderWithRouter(
<QuickSearch />
);
const input = getByPlaceholderText(/Search for a movie or person/i);
expect(searchAPI.searchMulti).not.toHaveBeenCalled();
act(() => {
fireEvent.change(input, { target: { value: 'Aladdin' } });
});
expect(searchAPI.searchMulti).toHaveBeenCalledTimes(1);
});
My problem is that I don't want to mock api in every test file that needs it. Instead, I would like to put api in a __mocks__ folder so that other tests can use it you, too.
How can I do that?
I am making a Vue JS project inside Laravel Project
how can I call data from other JS File?
what I have now is
MainComponent.vue
data() {
return this.getData()
}
DataComponent.js
module.exports = {
getData() {
variable1: [],
variable2: []
}
};
i dont know if i do it correctly but maybe someone could help. Thank you!
not sure what you're trying to do but maybe this will help:
MainComponent.vue
import { _data } from './DataComponent'
data() {
return _data
}
DataComponent.js
export const _data = {
var1:[],
var2: []
}
you must export js module then import inside Component for example
Test.js
module.exports = {
getData() {
variable1: [],
variable2: []
}
};
MyComponent.vue
import { obj } from 'your_js_file_path/Test'
then you can use forexamle inside some method
obj.getData();
I am trying to separate my axios calls from my main vue instance by importing them instead of calling them directly in the created hook.
I have this in a separate file called data.js
import axios from 'axios'
export default{
myData() {
return axios.get(`http://localhost:8080/data.json`)
.then(response => {
// JSON responses are automatically parsed.
return response.data;
})
.catch(e => {
return this.myErrors.push(e)
});
},
And in my vue instance I have the following:
import myDataApi from '#/api/data.js'
export default {
name: 'app',
components: {
myDataApi, // not sure if this is correct
},
data: function () {
return {
myInfo: '',
}
},
created() {
this.myInfo = myDataApi.myData();
console.log('this.myInfo= ', this.myInfo)
},
I am trying to populate myInfo with the json called by myData. This returns [object Promise] in Vue devtools and the as PromiseĀ {<pending>} in the console.
All the data I need is inside that PromiseĀ {<pending>} in an array called [[PromiseValue]]:Object so I know it is working, I just need to know the correct way implementing this.
I don't have a development environment enabled to test this at the moment, but I do notice that you are trying to assign a variable the moment that the component is initialized. This object is a promise, but you're not handling the promise after it is resolved inside the component where you have imported it.
I would recommend trying to handle the promise inside of the actual component, something like:
import myDataApi from '#/api/data.js'
export default {
name: 'app',
components: {
myDataApi, // not sure if this is correct
},
data: function () {
return {
myInfo: '',
}
},
created() {
myDataApi.myData()
.then((data) => {
this.myInfo = data
console.log('this.myInfo= ', this.myInfo);
});
.catch((e) => handleError) // however you want to handle it
},
Just to add to #LexJacobs answer. I omitted the parenthesis around data in .then() as seen below. Vue was squawking about data not being available even though it was. This solved that problem, although to be honest I don't know why.
myDataApi.myData()
.then(data => {
this.dataHasLoaded = true;
this.myInfo = data;
})
.catch(e => {
this.myErrors.push(e)
});