Listen to custom events from other Controllers in Spine.js - spine.js

I have created a Spine Controller and I want to trigger a custom event 'Create' from inside one of it's methods.
Then I would like another Spine Controller to listen for that event.
How is this possible using Spine.js's custom event methods?

Custom events don't have to be global. You can can trigger/bind events per controller instance, but not per controller class. For instance
class PresenterController extends Spine.Controller
giveSpeech: (message) ->
#trigger("speech",message)
class App extends Spine.Controller
addKeynote: ->
#speaker = new PresenterController
#speaker.bind("speech",#listen)
listen: (message) =>
alert("I heard " + message)
But you can't get something like PresenterController.bind("speech")
The reason is that Model uses #extend Event, which adds methods to the class, but Controller uses #include Event, which adds methods to the instance. Model achieves the appearance of having instance bindings because it defines its own implementations of trigger, bind, and unbind

You can trigger events in Spine like this
Spine.trigger "Create"
In you're other Controller you can bind the event to a method like this
Spine.bind "Create", #create
You have to define a method with the name create in this Controller:
create: =>
# Create action
Because the custom events are global I would suggest using the controllers name as a prefix.
You could use ControllerName:Create for example:
Spine.trigger "ControllerName:Create"

Related

onPropertyChanged - How to switch propertyId from external class

I have a model that extends BaseObservable. I have a view model that contains a reference to the model and subscribes to property changes within the model. How do I switch on the Model.propertyId from within the callback in the view model? In the sample below BR.assignedId is the property in the model. For example:
View Model
public void onPropertyChanged(Observable sender, int propertyId)
{
switch (propertyId)
{
case MyModel.BR.assignedId://compile error
notifyPropertyChanged(BR.assignedImage);
break;
}
}
I suggest you to read Observer pattern. The code above has Entities : Observer and Observable. Observer has an Observing method. Any class which wants to observe the 'Observable' needs to register itself as 'Observer'. Observable calls the observing method on the Observer and this is how the usual call back works. (names of classes and methods may be differnt , I used as per the intent and context)
Check 'ViewModel.java' class would be implementing some 'observer' interface which would be having the method 'onPropertyChanged ()'. you will have to set the object of ViewModel.java in Model.java. (check you should be having a method with a name like addPropertyChangeObserver (), though it may be differnt but similar method. Use this method to set the object of ViewModel.java in Model.java. Now Model.java would call the method 'onPropertyChanged' on ViewModel.java.
if you wish to modify something on the Model then check the sender parameter. You can add another method in the interface implemented by Model and can do modifications on Model using it or can simply typecast the sender after checking its type with instanceof and can perform the process on Model.java from the callback method.

Dynamically changing the datasource of model in strongloop

I have created a mixin in which I am trying to override the getDataSource method of all the models like:
Model.getDataSource = function() {
console.log('Overriding the getDataSource for model ' + Model.modelName);
// Code to attach the new datasource based on some logic by
// invoking Model.attachTo(datasourcename) method
}
I have models created which have datasource set to "db" initially. When I make a request to the application
it should attach the datasource dynamically to the models. I am not sure what I am doing wrong above as above
method is never invoked for the models which I have created initially but it gets invoked for all dynamically
created models(using createModel method).

In MVC, is a controller an object or a function?

I am learning Symfony2, and part of the documentation on controllers states that the methods on the controller object are actually the controllers, whereas the object is more of a controller container.
Which part specifically is referred to as the controller(s)? I'm new to MVC and OOP, so I'm just trying to make sure I have it right.
the page describes actually a convention endorsed by Symfony2 creators.
in some MVC frameworks (esp. in Java) controllers are implemented by one-class-per-controller convention, e.g.:
class ListContactsController {
public function start() {
// query db...
return ...;
}
}
class AddContactController {
public function start($name, $details) {
// insert into db...
return ...;
}
}
note that every controller-class has one method start() that defines what the controller actually does
in other MVC frameworks (like Symfony2 or cake-php) controllers are implemented by one-method-per-controller convention, grouped together for convenience, e.g.:
class ContactsController {
public function list() {
// query db...
return ...;
}
public function add($name, $details) {
// insert into db...
return ...;
}
}
here the convention assumes every controller is implemented as a method rather than a separate class with a particular method like start()
EDIT: another way of thinking about this difference is this:
one-class-per-controller assumes there is one controller instance (might hold internal state) and when user interacts with the view, view is communicating with that controller instance via callbacks i.e. methods in controller's class.
one-method-per-controller assumes any state is contained within parameters that are passed to methods, and when user interacts with the view, view is communicating with separate controllers/actions. those controllers are seen as independent concepts.
In the example page you shared, the "class HelloController" is the Controller and its' functioned are Controller "Methods".
Okay, they are referring to the default method, indexAction() as the Controller.
In this MVC architecture (and most others, if not all) the "index" method is the default method (function) called when that controller is requested.

Get action name from within controller.php in the components

Is there a way to get the current action name from within the Controller.php init function ?
Thanks
In general, you can call $this->action->id within descendant of the CController class.
Or you can use Yii::app()->controller->action->id through whole application.
But the method init() was called before the controller started to execute (see http://www.yiiframework.com/doc/api/1.1/CController#init-detail)
As you can see here: http://www.yiiframework.com/doc/api/1.1/CWebApplication#runController-detail actionID will be passed to method run() only after init():
$controller->init();
$controller->run($actionID);
As v2p said, after init() run, we can get the controller id by Yii::app()->controller,also behavior id by Yii::app()->controller->action->id;Another way: Yii::app()->getController()->getAction()->id;

Yii: attaching events to models

I have a User model which is bundled in a module installed on my Yii application. This module is third party and I do not want to alter its code.
I also have a Cv Model that has a BELONGS_TO relation with the User model.
My question is: How can I delete the cv when a user is deleted ?
I know that I can achieve this with on delete cascade ... on mysql. However, i do need to delete other data such as a photo, files, etc.
What I have tried
I have created a component that is preloaded on my application. This component attaches to an onAfterDelete event
class EventListener extends CComponent
{
public function init() {
Yii::import("application.modules.users.models.User");
User::model()->attachEventHandler('onAfterDelete', array($this, 'deleteUser'));
}
public function deleteUser($event)
{
// stuff here ...
}
}
However this does not work.
Any suggestions ?
This may help you.
User::model() is a singleton
$user1 = User::model();
$user2 = new User; // will be used in insert action
$user3 = User::model()->findByPk(10); // will be used in update/delete action
$user1, $user2 and $user3 are completely different objects.
You can attach events to objects, in this case you have to add events to all these 3 objects individually.
$user1->attachEventHandler(...);
$user2->attachEventHandler(...);
$user3->attachEventHandler(...);
look like Yii does not provide any way to add events at Class level.
Well, guys, I have just stumbled upon the same problem and I solved it this way:
You should use the init() of a Model, not your event listener collection class.
In my case I have devModel class:
public function init()
{
parent::init();
$this->onLicenseUpdated = array(new MEventProcessor, 'licenseUpdateHandler');
}
And the handler is licenseUpdateHandler($event) in a MEventProcessor class.
This way every time you work with model instance, it'll call init() for every object and attach the event handler to every instance of this Model.
Now any time the event (in my case onLicenseUpdated()) is invoked for the model - the handler will be called too.
You could also to use Behaviors.
1 - behaviors can listen to events : you just have to override their events() method
class MyBehavior extends Behavior {
public function events() {
return [
ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
];
}
public function beforeValidate($event) {
// ...
}
}
2 - although it is more common to attach a behavior to a component in the component's behaviors() method, you can also attach them dynamically and keep the original code unmodified :
use app\components\MyBehavior;
// attach a behavior object
$component->attachBehavior('myBehavior1', new MyBehavior);
You will find some useful documentation here :
yii 1 : http://www.yiiframework.com/doc/api/1.1/CBehavior
yii 2 : http://www.yiiframework.com/doc-2.0/guide-concept-behaviors.html