This looks like it has the potential to be what I was hoping someone would make. Looks excellent so far, thanks for sharing!
Once you get used to it, you will actually see that it's even more flexible and easy to write applications and can even benefit your backend code as well. E.g., I have stopped creating models on my backend code and instead, I am writing modules that may query a table, or two tables or talk to another API. I am using them whenever it makes sense to, not just the controllers.
My background is from creating both backend and frontend apps and I hope the above to holds true since I've been there but let me know if I am wrong here.
The client model is different from the server model!
Of course, it is not totally different, but different enough to warrant separate treatment, and the most differences are fundamental, not just differences in detail.
The client model is mostly hierarchical, not a cross-connected graph, so it contains multiple "tree-ifications" of the server model. Also, most parts of the tree have much fewer fields, as not all data fields are meant to show up in the client. And that set of fields might be different in different corners of the client. One server model class might have multiple vastly different representations in the client model, depending on the corner of the user interface.
On top of all that, the client model contains transitional information about the state of the user interface that is not represented in the server model at all, such as which item in a list is selected, which part of a map is shown, which parts of a document are folded or opened, and so on.
Finally, the client model operates mostly in an "open world" fashion, while the server model is a "closed world". I'm using these terms in the meaning of Prolog terminology.
That is, the client must always assume that on server side, there are more records that it currently has, and that each record may have more fields on server side than the client is aware of. So with very few exceptions, the client should always perform minimal changes (insert/update/delete), not bulk changes. And after reach change, it should retrieve a fresh state from the server, because another client might have changed something as well, and because the server might have decided to perform some other changes (update calculated/cached fields) as well.
The server, on the other side, usually has the whole database at its fingertips, so it can safely perform large-scale changes, not just minimal changes.
Vuex, Redux, etc just don't make sense in my brain, so I've never used them. I built this because I wanted something simple to interact with my Laravel backends. Most of what I do is CRUDdy, and this is super helpful for that.
I've been using Django for a decade and there are simple queries that were impossible with the ORM until recently.
If you have to twist the ORM into spitting out the SQL you already know how to build, you know there's something wrong.
New to vue.js and maybe I'm doing things... Wrong? But I don't think I need this.
My approach is very angularJs-esque but I have a root component 'main.vue' which basically acts as my index.html. When I want to send a REST call I've got a method setup which handles GET calls and another for POST calls... I use them how you would call an angular service, and it works... Well (at least I thought so until seeing your post).
Can you explain why I'm stupid and everything I've done is wrong?
Haha I cannot, because you probably aren't stupid and haven't done everything wrong.
The thing I like about this approach is that it removes the need for manually:
1) writing `saveCustomer` or `getCustomer` methods on my vue instance
2) tracking validation errors for each model. So if there's a collection of models on the page, I can super easily show errors for each
3) keeping track of loading indicators
4) applying the server's response to the model.
In your setup, what happens if the HTTP call fails? You have to do something with that error right? What happens if you want to show a spinning indicator that the call is working. If the server returns a response (on say a fetch or an index), what do you do with that response?
I think this (https://github.com/aarondfrancis/vue-model#update-a-model) is a good example to try to work out with the centralized service approach, and see which you like better.
Try it for one model, and then think about if you had to do two or three similar resources.
Hope that makes sense!
To answer your questions, if http call fails I'm currently handling it in a .Catch. I haven't done much specific error handling yet, was probably going to do a bunch of if statements to figure out the nature of the error and then output relevant messages to toast.
For the loading indicator(s) I was planning on using just one, globally, like YouTube does - their slim red line that runs a long the top of the viewport?
I'll definitely look more into your library but I'm hesitant to bulk up my app unless something provides critical functionality. Using Quasar framework right now and already a little conserned with load times and bulk. Although I haven't built for production yet with full minification, etc.
Thanks for your time in responding to my stupid questions!
Also you may be interested in http://derbyjs.com/ and do some research about operational transformations.
Ah, and please do not forget that in a real app you need to lock the records users are editing, but not indefinitely.
Thanks and happy coding!
Also how does it work with nested models returned from the server? Can I do user.tickets.push(newTicket) in some form?
To "reset" a form, I guess you could get it again from the server via customer.http.fetch()
Edit: what this is missing is essentially an implementation of forms. That doesn’t necessarily need to be a part of this project, but it should be used together with this. Otherwise you end up at least temporarily persisting changes that were never saved. See the relationship between Django models and forms.
Also, one feature I have implemented in at least one of my apps has been using WebSockets to deliver new, updated, and deleted models from the server. That could be a super powerful addition here.
This is business logic and it's dependent of the UI. If you have a Save button but the user doens't save and leaves the page, on change route you reset the model. If it doesn't have an explicit button, on change route you save the model. It has nothing to do with the framework.
If you mean the library doesn't have a way to reset the model to its original state, it doesn't take too long to implement, just call fetch as the author says or when you load the original model store a copy somewhere, even inside the model itself.
Calling fetch all the time because the user navigated away doesn’t make sense performance wise.
Think about it. If Django/RoR had their ORM make all modal instances global singletons and any view there could modify the properties of the model, but for persistence still had to save them to the DB, would you want all of your views to have to roll their own reset code? Would you trust such code? No. That would be nuts. So why is that ok on the client side? Local state is ok for emphemeral data. Use it instead of modifying global state with data that is not ready to be committed.
Question for the author: is this "production-ready", or is it a toy project? If I start using this, do I have to worry about you abandoning the project six months down the line as you become interested in other things?
That in my mind is the biggest issue with open-source in general: people release stuff into the wild but don't follow through.
This free software comes with no guarantees either explicit or implied.
That being said, I use it all the time so I plan on maintaining it. You are also welcome to contribute if you find something that needs fixing
I don't use Vuex, I find it to be more complex than I need. I build a lot of CRUDdy apps that are pretty straightforward, so I've never dived into it much. I've watched the lessons on Laracasts for it, but just don't need it yet.
This is to replace the instances where you have a update() methods in your vue instances that set up axios, organize the data, send the request, and handle the response.
It's very much for restful resources.
() I'm not seing that a lot from the frontend people here.