How to split one response into several Vuex modules? - vue.js

I've got a small Vue/Vuex/Rails app that I'm building and am trying to figure out the best way to handle this scenario.
Upon login or page refresh, I have a mixin that checks to see whether currentUser is in state. If it's not, it runs a call to my api to retrieve the currentUser, as well as that user's deeply nested relationships. Something like this:
currentUser: {
...user data
groups: [
categories: [
items: [
...item data
]
],
],
}
That api call lives in user.module.js. My question is, rather than storing the entire user object with all of its nested data in user state, is it possible to split out all of that data into separate modules (eg.: groups.module.js, categories.module.js, items.module.js)?
This would allow me to make a much simpler action and mutation by going straight to item in the items.module.js.
I appreciate any help!

Yes, definitely you should split them in multiple modules, otherwise, your data structure will get really difficult to deal and understand. After you have defined how will be structured your modules, when you get the user data you can dispatch as many actions you need to each module to populate their states.
I created a codepen to show you.

Related

Accessing site options via a REST API

I'm building a REST API powered SPA application and I'm trying to decide on the best way to deliver "global options" via the API. By global options I mean an assortment of random fields that relate to the application as a whole rather than being associated with one specific model, for example brand logos and contact details that need to be accessible from multiple locations within the app.
Something like Wordpress would store these in an options table and access them via a php function using the option name, however since this is a REST API I'm not sure how I would go about accessing/updating multiple options without making lots of requests for each one.
I know a lot of projects just use a json file to store this data, but it specifcally needs to be editable via a CMS and served via the API. The following are two methods that have come to mind, but none of them feel like complete solutions:
1: An options table with one generic endpoint that takes a query string specifying which fields you want to access. This works for getting data, however updating data seems to get a bit messy and the only way I can think to do this is by sending an object of key/values pairs to bulk create or update the options:
GET: example.com/api/options?pick=logo,contact_phone,contact_email
POST: example.com/api/options
{
contact_email: "info#example.com",
contact_address: "123 Test St"
}
PUT: example.com/api/options
{
contact_email: "info#example.com",
contact_address: "123 Test St"
}
2: Breaking fields into groups and storing them as a json field in a "pages" table, this solves the creating and updating issues but breaks down when you have fields are used in multiple locations, and they aren't really pages so it's not very REST like.
GET: example.com/api/pages/contact
POST: example.com/api/pages
{
name: "contact",
values: {
email: "info#example.com",
address: "123 Test St",
}
}
PUT: example.com/api/pages/contact
{
values: {
email: "info#example.com",
address: "123 Test St",
}
}
I also need to take into account the issue of access permissions, for example the logo field would be accessible to the public, but the user support contact number would only be accessible to logged in users. With the first example you could have an extra permission column for each option, but this wouldn't work for the second option.
I've been googling but have failed to find any good information about this topic as REST schemas/documention generally only deal with concreate entities, so any insight into how this is achieved in real world applciations would be great!
Cheers,
Cam

VueX within Mixin

Before writing too much code, I thought I'd conceptually understand whether what I am doing is correct.
I have some components, that import a mixin. The mixin has a web api call to retrieve the some links from the (HATEOAS) API, so the UI can use the links without forming its own links. These would look something like:
[
{
"Rel": "GetSupportingData",
"Href": "https://api.com/SupportingData"
},
{
"Rel": "Search",
"Href": "https://api.com/Search"
}
]
So the MIXIN has a method called GetLink("Search") that would retrieve the links from the API and return the link requested.
This is all ok, but as the mixin is imported to a lot of components, I don't want each time its used to make the WEB API call to get the links before filtering them. I was therefore wondering if I should use Vuex to manage the state of the links and retrieve them if the store count was zero?
The examples of Vuex I have seen instantiate it on the component, so what I'm doing feels like it may not be correct.
You can store the web api links to store that is one approach, but when you refresh the page again the store needs to be filled with the api links
So, the alternate approach is to use localStorage or indexedDB of browser
Everytime when you load the application first it goes to localstorage or indexedDB and checks for the api links. If its present, it restores to Vues store. Or calling mixin method to fetch api links and loads to browser storage and vuex store

How to reuse data obtained by axios calls between VueJS components?

I am sorry if this question has already been asked, but i can't seem to find a clear explanation for my problem.
Problem: i have a web page showing a client's problem. This page need data like client ID or problem number to display it in different parts of the page (header, menu, body). This data is obtained with axios calls.
So i have multiple components which need the same data from the same axios call.
I can't understand how it is possible to make one axios call, for client ID for example, and share it with multiple components instead of making an axios call each time i need the data.
Are mixins a solution?
I have tried to use a mixin:
Vue.axiosGet({
methods: {
request: function(url) {
return axios.get(url).then(response => {
return response.data;
});
}
}
});
But now i don't know where or how to store the data i'll get.
EDIT: i forgot to precise that i don't want to use VueX.
You say that you don't want to use Vuex, but why not? I would recommend you use the Vuex store to achieve what you're looking for. A vuex store will cache/hold information in it, meaning that you can easily access it on a different page. Vuex would solve your problem and allow you make a call once, and later access the data. No need to re-invent the wheel, it's an effective way to achieve what you need.
If you really don't wanna use Vuex, there're always solutions like nedb, but I'd strongly recommend Vuex.

Pwa wrong to consider api cache instead of db?

im building a specific book reader like app.
Main page call api/booksList and receive the json array containing each book info like:
[ { id: server_db_id, title: "title test", sum: 10 , date: ... }
]
ans its cached after the request, so im not saving the book list into indexedDB, localStorage or other storage. If i need one specific book, i just call the api book list again and filter it. Is that bad design? (book will be over 200 items)
Whe user open the book, it call the /api/book/book_id and its cached too, the opened book response is a json list of the lines of the book, eg:
[
{
id: ...
content: "This is line...lore ipsum..."
....
}
]
I put the api response inside vue data variable and the component is rendered correclty
Im not using any kind of handler for keeping this offline by my hand. To detect if user already opened this book, i just call the api, check if errors happened or the responde body has content.
Is that a wrong, bad or stupid decision? Will this hit the quota limit api or other kind of limitation? The "gods" of pwa will raise the finger to me and say: WAAAT. (im not using indexedDB at first because it need some models handling and i want to make things easier if possible)
I my self was just researching this and concluded, at the moment I am going to go with this method, where I use cache for assets, js, css, html etc based on their matching routes.
Then when it comes to data e.g. json requests etc. Its best to store them in indexedDB (or an equivalent), which really does not require a model or schema as such.
See Jake Archibald's IndexedDB-Promise library https://github.com/jakearchibald/idb its really simple to get your head round.
Though both Jake and Addy say it's not a defacto rule, so you can decide ultimately what is best for you.
Read this for better clarification
https://developers.google.com/web/ilt/pwa/live-data-in-the-service-worker
https://medium.com/dev-channel/offline-storage-for-progressive-web-apps-70d52695513c
It helped me to make a better decision on how to go about moving forward.
Recommendations Also
Check out PWA Training: https://developers.google.com/web/ilt/pwa
Workbox: https://developers.google.com/web/tools/workbox (This has sped up my development massively!)
Codelabs: https://codelabs.developers.google.com/ (Search PWA)
The guides on here are really good at taking you through everything you need.
Good Luck with your PWA
Random thought (edit)
One thing that makes me question this though is based on some of the examples and guides I have seen is that, data storage is handled in a more ad-hoc manner. For example, if the PWA calls out an API, there are two methods I have come across where you can either manage cached data in the application or in the service worker, e.g. if your API calls to get JSON fails in the app, it can revert to getting data in the indexedDB which hopefully was pre-cached the first time your app called the API.
Or you can use self.addEventListener('fetch', (event) => { ad-hoc stuff here }) this is where you can match either an asset, or data request and hijack the response with either a cache or indexedDB response. Which prevents the need handle offline data in your app.
The first method makes me feel uneasy so i'm gonna go with the addEventListener approach both in the service worker cause thats what it is there for plus my app does not then have to worry about that.

Retrieve the list of friends that did a custom action on a custom object in open graph 2

I would like to do something like facepile using the graph api with open graph 2 actions : from a custom object and a custom object, give me the friends (using my facebook application) that did this action on this object.
The problem is that using FQL, I cannot query custom objects and actions. Using the graph API, I cannot find a way to intersect the list of my friends with the object I'm interested in.
The best I could do was the following using the batch mode of the graph API :
batch=[
// First we get the list of friends that are using my facebook application
{ "method": "GET", "relative_url": "fql?q=SELECT+uid+FROM+user+WHERE+uid+IN+(SELECT+uid1+FROM+friend+WHERE+uid2=me())+AND+is_app_user=1+LIMIT+0,49", "name": "friends"},
// Then query each friend to get the list of objects that went through my namespace:testaction
{ "method": "GET", "relative_url": "{result=friends:$.data.0.uid}/namespace:testaction" },
{ "method": "GET", "relative_url": "{result=friends:$.data.1.uid}/namespace:testaction" },
...
{ "method": "GET", "relative_url": "{result=friends:$.data.49.uid}/namespace:testaction" }
]
It's quite inefficient and does not fully resolve my issue since :
I still have to filter the results to get only the one that matches
the object I want
If there is a large number of objects in namespace:testaction, I have to go through paging, doing more queries (I try to minimize the number of queries)
Do you see a better way to do this ?
This probably isn't exactly what you're looking for, but given the fact that facebook (AFAIK) doesn't provide (and will probably never provide) the ability to do this. I think you should simply store the information yourself and then query the data from your own database. It would be like what you're doing in your question, but you can optimize it since it's your database.
I'm sure you thought about this already, but someone had to say it.
It's now possible to do this with one Graph API request:
GET https://graph.facebook.com/me/friends?limit=50&fields=name,namespace:testaction.limit(100)
see field expansion and updates to the graph API.
If the answer derickito gave is not enough, you should explore getting your app on the Facebook white-list (aka become a partner) to get at some the private Graph API where this functionality might exist, but is not available for "normal" application that are stuck using the public Graph API.