CanJS - Communication Management

I am learning CanJS now, so I want to try a very small demo. The demonstration is that you will have different types of balance replenishment plans, which are displayed on the top (Radio buttons), and, choosing each plan, the corresponding prices will be displayed in the table below.

For this demonstration, I create two Model files, 2 Control and 2 Template, my question is, how can two controls interact with each other? What is the standard way?

Now I directly call the control method through my instance, but I'm not sure if this is the right way to do it. Also please explain Can.Route.

Exit http://jsfiddle.net/sabhab1/2mxfT/10/

Data

var CATEGORIES = [{id: 1 , name: "2G Internet Recharge"}, {id: 2 , name: "3G Internet Recharge"}, {id: 3 , name: "full talktime Recharge"}, {id: 4 , name: "Validity and talktime Recharge"}, {id: 5 , name: "National and international roaming"}]; var RECHARGEAMOUNTS =[{ id: 1 , values : [{amount: "Rs. 100" , benefit:"300 MB" ,validity:"30"}, {amount: "Rs. 200" , benefit:"1 GB" ,validity:"30"}] }, { id: 2 , values : [{amount: "Rs. 10" , benefit:"300 MB" ,validity:"30"}, {amount: "Rs. 99" , benefit:"100 GB" ,validity:"90"}] }, { id: 3 , values : [{amount: "Rs. 80" , benefit:"1 GB" ,validity:"50"}, {amount: "Rs. 99" , benefit:"100 GB" ,validity:"50"}] }, { id: 4 , values : [{amount: "Rs. 55" , benefit:"30 MB" ,validity:"10"}, {amount: "Rs. 200" , benefit:"1 GB" ,validity:"30"}, {amount: "Rs. 99" , benefit:"100 GB" ,validity:"90"}] }, { id: 5 , values : [{amount: "Rs. 880" , benefit:"100 MB" ,validity:"90"}, {amount: "Rs. 550" , benefit:"2 GB" ,validity:"30"}, {amount: "Rs. 1000" , benefit:"4 GB" ,validity:"90"}, {amount: "Rs. 1550" , benefit:"10 GB" ,validity:"90"}] } ]; 

Model

 //Model Category CategoryModel = can.Model({ findAll : function(){ return $.Deferred().resolve(CATEGORIES); } },{}); //Model Category ReachargeAmountModel = can.Model({ findAll : function(){ return $.Deferred().resolve(RECHARGEAMOUNTS); }, findOne : function(params){ return $.Deferred().resolve(RECHARGEAMOUNTS[(+params.id)-1]); } },{}); 

Control

 **// Can Control var CategoryControl = can.Control({ // called when a new Todos() is created init: function (element, options) { // get all todos and render them with // a template in the element html var el = this.element; CategoryModel.findAll({}, function (values) { el.html(can.view('categoriesEJS', values)) }); this.options.rchAmtCtrl = new RechargeAmountControl("#rechnageAmountView"); }, 'input click' : function( el, ev ) { var id = el.data('category').attr('id'); console.log(id); this.options.rchAmtCtrl.update(id); } }); // Can Control var RechargeAmountControl = can.Control({ // called when a new Todos() is created init: function (element, options) { // get all todos and render them with // a template in the element html this.update(1);//this.update(id,this.element); }, update : function(id){ var el = this.element; ReachargeAmountModel.findOne({id: id}, function( rechargeAmount ){ // print out the todo name //console.log(rechargeAmount.values[id].attr('benefit')); el.html(can.view('RechnageAmountEJS', rechargeAmount.values)); }); } });** 

View

 <form id='categoriesView'></form> </p> <table id='rechnageAmountView'></table> <script type='text/ejs' id='RechnageAmountEJS'> <tr> <th>Recharge Amount</th> <th>Benefits</th> <th>Validity(Days)</th> </tr> <% this.each(function( rechargeAmount ) { %> <tr> <td> <%= rechargeAmount.attr( 'amount' ) %> </td> <td> <%= rechargeAmount.attr( 'benefit' ) %> </td> <td> <%= rechargeAmount.attr( 'validity' ) %> </td> </tr> <% }) %> </script> <script type='text/ejs' id='categoriesEJS'> <% this.each(function( category ) { %> <input type="radio" name="category" <%= category.attr('id') == 1 ? 'checked' : '' %> value=<%= category.attr( 'name' ) %> <%= (el) -> el.data('category',category) %>> <%= category.attr( 'name' ) %> </input> <% }) %> </script> 

Main challenge

 new CategoryControl("#categoriesView"); 
+4
source share
1 answer

There are several ways to do this.

1. Direct calls

This is what you are doing, and not necessarily wrong. To make things a little more flexible, you can pass a class or instance of RechargeAmountControl when initializing CategoryControl instead of using it directly.

2. DOM events

Here it is a little more relevant to event-oriented architecture. If you usually want to notify other controls, you can simply trigger an event and make them listen to it. Something like this: http://jsfiddle.net/2mxfT/11/

 ' rechargeAmountUpdated': function(element, event, id){ var el = this.element; console.log(arguments); ReachargeAmountModel.findOne({id: id}, function( rechargeAmount ){ // print out the todo name //console.log(rechargeAmount.values[id].attr('benefit')); el.html(can.view('RechnageAmountEJS', rechargeAmount.values)); }); } 

3. Observed

Another option is to use Observables to maintain overall health. This is a great way to focus on data and let live bindings do the rest. To make things more flexible, a state object must be passed during control initialization (see http://jsfiddle.net/2mxfT/12/ ):

 var state = new can.Observe(); new RechargeAmountControl("#rechnageAmountView", { state: state }); new CategoryControl("#categoriesView", { state: state }); state.attr('rechargeId', 1); 

And then you can just listen for attribute changes in RechargeAmountControl as follows:

 '{state} rechargeId': function(Construct, event, id){} 

This handler will be called whenever you update your state. Watch.

And here is also can.route . Basically, can.route is an Observe that stores its state in a location hash. In the example above, for example, #!&rechargeId=1 (unless you initialize a specific route, for example can.route(':rechargeId') ). If the location hash changes, Observe will be updated and vice versa.

+5
source

All Articles