I have a can.Model with defined findOne, findAll methods. Sometimes however it is required to create model instances from plain objects, e.g. these objects are bootstrapped in html as globals during initial page load.
The problem is that these instances are not merged with instances stored in can.Model.store object. Moreover they are not getting stored there while they have defined id attribute. Is it expected behaviour? What is the right pattern to create model instances bootstrapped in html as variables?
Only models that are bound to (e.g. having data displayed on the page) will be added to the store. The store is only used for keeping those models. If nobody is listening to model changes there is no need to keep them stored (in fact, it would create a memory leak).
You can verify it like this:
var model = new MyModel({ name: 'David' });
model.bind('change', function() {});
Related
I would like to understand what is the difference between mount and render methods in Livewire components, since I have seen examples where both are used to define initial state of variables. For instance, when you instantiate a variable with records from the model, ¿which is the right place to load the data using the ORM syntax?
The mount() method is what's called a "lifecycle-hook". There are a few more of these kind of methods in Livewire, which are outlined in the official documentation - https://laravel-livewire.com/docs/2.x/lifecycle-hooks - while the render() is the final method that's called to render the actual view.
The mount() method is the construct to the component. This is where you pass in the data that the component needs. This method is only called once, on the initialization of the component, which means its also typically where you set up initial values that aren't constants.
However, since public properties of a Livewire component can only be collections, the instance of a model, arrays or native PHP types like string and integer, you can't pass more "advanced" types that relies on a state - for example like the pagination of a query of models.
That is why you would sometimes need to pass data to the component via the render() method, like you would when returning data in a normal Laravel controller. Another reason to pass data here is that the data is not exposed in JavaScript, like the public properties of the component is.
The render() method is called at the end of every lifecycle request, but before the component dehydrates. Official documentation has more detailed information https://laravel-livewire.com/docs/2.x/rendering-components#render-method - the data defined here isn't a property of the class, and thereby not accessible in the other methods in the component.
So to answer your question, it depends on what type of data you are passing, if the data should be accessible in the other methods in the class or if it's sensitive such that it shouldn't be visible in the JavaScript object attached to the component.
mount method is like any constructor and you can use it in multiple cases, in other you don't need it. For example, if you have a nested component into a full page component, but initially the nested properties are null or require any definition, you define it there. Is used also for the route model binding definitions but you need be clear that any definition you declare here will not be updated, hydrated or suffer any changes after you initialize the component. Mostly, this is the difference with the render method.
This is just a theoretical question, I am new to PyQT. I am not able to identify classes or code examples that will show how the model updates the data (if that is done via Qt)
Right now my understanding is that the programmer is responsible for writing the methods/code for updating the data when a change is done in the model data.
Am I correct ?
Update: It seems that my question needs a drawing :-)
So it is data as in data stored in a database. By my understanding the data in this picture is the data stored in the database not the data that the model is based on which is a subset of the data in the database
Try following some of the tutorials and look at the example programs provided with PyQt or PySide.
A model is an object which stores data. This can be as simple as a list of strings. A view is an object which displays data. Qt provides some standard models for storing common types of data and some standard views for displaying common types of data. For simple cases you can use these pre-built components. These components have standard methods for adding or removing data from the model, or updating the view as the model changes. These changes are propagated from the model to the view, or from the view or control widgets to the model, using signals. Thanks to standardized naming of methods and signals this all works pretty seamlessly.
However your specific data storage or data presentation needs might be a bit different. In this case you can implement a custom model or a custom view, or if necessary both. You implement your custom model (or view) by subclassing one of the classes provided by the framework. You have to implement specific named methods on these subclasses because it's the standard naming that makes the automatic behavior with other components work, but can also add your own custom methods and such as you see fit.
Further to MiniMe's comment:
Lets look at an example. Qt Models have a xx.setData() method to update a data item, which takes parameters specifying where in the model the data goes (index) and the new data. When you implement that method, you perform the work of updating the data to whatever underlying storage mechanism you use (e.g. a list or dictionary) and emit the xx.dataChanged() signal. If any views are linked to this model, they will have subscribed to this signal and so will update themselves automatically.
def setData(self, index, value):
# Update the data in the underlying python list self.my_list
# The index object is of a data type provided by Qt. To perform
# this operation we have to extract the row number where the change
# is to be made, then use that to update the appropriate entry in
# the list.
self.my_list[index.row()] = value
# Create a PyQt modelIndex object based on the row number that was
# updated. The self.index() method is provided by Qt.
modelIndex = self.index(index.row())
# Send the modelIndex of the change to any connected views so they
# know to update themselves
self.dataChanged.emit(modelIndex)
# In reality we'd do some validation checks and return False if there
# was a problem and the data change didn't happen.
return True
Similar methods would need to be implemented for adding a new data item in the list or removing a data item from the list. These methods would make the change, send a signal indicating which part of the model had changed to any attached views, then return. I hope this is more helpful.
Using Durandal, I have two view models within my app, let's say vmCompanies & vmEmployees. I have two views, one for each view model and within each, you can see all companies & all employees.
However, when I'm loading my employees, in the DB they have an ID for which company they are employed by. What I'd like to do is the following pseudo:
From within the vmEmployees, get a reference to the vmCompanies
If the vmCompanies has already been initialized (which I know it is 99% of the time), get a reference to it so I can use something like linq.js to find the specific company this employee works for
If the vmCompanies has not been initialized (aka: activated), do so
This way I can avoid the requirement of the vmEmployees having it's own internal cache of companies. So far I've been unable to figure out how in Durandal to query and ask "give me this view model that you've already loaded." It seems like it has that internally because when I navigate between views, they are cached and not reloaded (same with the VMs)... I've just so far been unable to see how I can do it.
You can manually require() a view model by its ____moduleId____. As long as your view model module returns an object and not a function, you'll be dealing with a singleton, so you can be sure you'll get the correct instance.
If you're not sure what the __moduleId__ is, you can use this chrome extension to view your view model's properties, including __moduleId__.
However, instead of manually instantianting VMs, a better alternative may be to create a separate module that you use to store the cached companies. I have a data module with its own internal cache that I use generically for this purpose, but you could create one specifically for companies, and store that information in it. It could even be responsible for loading its own data, if that's appropriate.
Here's some simple code to help explain:
Note this uses the sugar syntax for require JS - if you're using the array-based syntax, you'll need to translate accordingly. I can help if needed.
//companies-cache.js
define(function(require){
//some auto-loading logic here, if you wish
var companies = ko.observableArray([]);
return {
companies: companies
};
});
//vmCompanies, vmEmployees
define(function(require){
var companiesCache = require("viewModels/companies-cache");
//additional properties for this specific VM
...
return {
companies: companiesCache.companies
};
});
Suppose, as part of an iphone application, I need to show user a list of some of some objects.
The model
Represents actual objects to be shown
Brainless data, collection of getters and setters
The view
Displays the list, passes received actions to a controller
Presentation layer
The Controller
Interprets actions received from the view and takes actions on data
Sits between the view and data
In this picture, would be be controller's responsibility to persist model to disk, or, should it be a part of Model's logic? Request to do this will come from a controller, but, should the controller know how to save data to disk, or should data know how to save itself to disk?
This is wrong.
Model is responsible for all the business logic. Additionally model is not directly aware of database or any other data storage medium. When model is initialized it receives factory for creating DAOs or DataMappers which are the ones responsible for storing and retrieving the informations.
Controller interprets the received information from view , and changes the state of model and view.
View either receives information from a persistent model via observer pattern ( classical MVC ) or request data from models ( Model2 MVC ).
I can see this going both ways. I would think that this logic goes into the model this way the controller is a little cleaner. Also, if you're using this functionality across models and it's mostly consistent e.g $person->saveData(), $user->saveData() then you could possible extend the base model so it would be inherited by other models and save you from duplicate code.
If this logic is incorporated into the model it would probably be a good idea to make it flexible enough so that the controller can override the persisting of data. So maybe, pass an argument into the model function $person->save( false ) This false would prevent the model from persisting the data but on default would be true.
I am developing an application that involves a type hierarchy and started by defining the models for each type via inheritance. When it comes to writing the corresponding controllers I am not sure how to approach the whole thing in a clean way. Should I write only one controller for the base type that is able to handle derived models or should there be one controller for each subtype? How should the view-controller bindings be set up to work with the different controllers?
You might want to check out SproutCore's new experimental polymorphism support: http://groups.google.com/group/sproutcore-dev/browse_thread/thread/b63483ab66333d15
Here's some information on defining sub-classes and overriding properties and methods:
http://wiki.sproutcore.com/w/page/12412971/Runtime-Objects.
From my (limited) use of Sproutcore, I've only been able to bind 1 view to 1 controller.
As such, if you are planning to use a single view (e.g. ListView) to display your data, then I think you will only be able to bind that view to 1 controller. This means the 1 base type that is able to handle derived models seems to be the way to go.
Typically you populate the content of ArrayController instances with the results of App.store.find calls. SC.Store#find can take an SC.Query instance, which typically looks like:
MyApp.myController.set('content') = MyApp.store.find(SC.Query.local(MyApp.MyModel));
This should return all instances of MyApp.MyModel, including any instances of MyApp.MyModel's subclasses.
The first argument to SC.Query.local can either be an SC.Record subclass or a string referring to the subclass. So if you've got some intermediary SC.Record subclasses, you might want to try using them there.
Controllers should just be proxies for objects, when dealing with single instances of your model. In other words, ObjectController can proxy anything. Here is what I mean in code:
You have two objects, Person and Student.
App.Person = SC.Object.extend({
// person stuff here
})
App.Student = App.Person.extend({
// student stuff here, you have have all Person things because you are extending person.
})
You then want to define controllers:
App.personController = SC.ObjectController.create({
contentBinding: 'App.path.to.person'
})
App.studentController = SC.ObjectController.create({
contentBinding: 'App.path.to.student'
})
note that you would only bind the controller's content to something if the person/student is a result of a selection, or some other flow where bindings fire. In other words, if you set the person manually (say from a statechart, as the result of an interaction), you would still define the controller but would do
App.personController.set('content', person);
You set up the controller differently depending on whether the Person is a 'top level' object in your app, or some intermediate object that gets selected. Also, you might only need one controller, you would only have a studentController and a personController if you were acting on a person and a student at the same time. Both are just ObjectControllers, and those can proxy anything.
Finally, in your view you would bind the relevant view element to the controller:
...
nameView: SC.LabelView.design({
layout: {/* props */},
valueBinding: SC.Binding.oneWay('App.personController.name')
})
...
note that the oneway binding is if the name is not going to be changed on the view, if the view can change the name, then just do a normal binding. Also note the path here. I am not binding to
'App.personController.content.name'
Since the personController proxies the object, you bind to the
'namespace.controller.property-on-object-controller-proxies'
If you are putting a lot of business logic in your controller, you are doing it wrong. Controllers should just be for proxying objects (at least ObjectControllers should be). Business logic should be on the models themselves, and decision making logic should be in statecharts.