EzDevInfo.com

canjs

Can do JS, better, faster, easier. CanJS - home

Defining two separate routers with can.Control.route in CanJS

I have two routes defined in different JS-documents, although both are included into the same HTML-file. Route 1 looks like this:

Router = can.Control({
   "invoices/:id route": function(data){
    //load an invoice by id
   }
 });

And the other one like this:

Router = can.Control({
   "receipts/:id route": function(data){
    //load a receipt by id
   }
 });

When i browse to #!receipts/1 both Receipts and Invoices are being instantiated. Why is that and how can I fix it?


Source: (StackOverflow)

Difference between JavaScriptMVC and CanJs

Call me stupid, but I'm quite confused. Are they the same and can.js is simply its successor? They seem to share quite a lot of functionality. As JavaScriptMVC is not updated as regulary as CanJs I think about switching to the latter. Does anyone have experiences with that?


Source: (StackOverflow)

Advertisements

can-model cannot getting data from .json file

I am trying to implement MVC using AMD in canjs. For that I am using requirejs. This is my domains.json file:

[            
"1":{"uid":     "1","urls": "domain1.abc.com"},
"2":{"uid":    "2","urls": "domain2.abc.com"},
"3":{"uid":    "3","urls": "domain3.abc.com"}
]

This is my domainModel:

define(['can'], function(can){
  SearchModel= can.Model({
     id: 'uid',
     findAll: 'GET /domains.json'
  },{})
  return SearchModel;
})

This is my controller:

define(['can','jquery'],function(can,$){
 domainController=can.Control({defaults:{view:"../view/search.hbs" }},           
  {
    init : function(element,options){   
        this.element.html(can.view(this.options.view,{
            searchlist : this.options.search
        }))
    }
});
return domainController;
} 

This is my main js:

equirejs(['can','controller/domainController','model/domainModel'],
 function(can, domainController,domainModel) {
   var Application = can.Control.extend({
    defaults :{ }
   },{  
        init: function(element,options){
         console.log('loaded');
         domainModel.findAll({}, function(domains){
            domainObject:{searchdomains : domains}
                 new domainController('#search',domainObject)
            });
        }
    })
return Application;
});

I am tracing out my code.I put breakpoints.On model breakpoints I am not getting values in local variables in chrome devtools.

The url property has 'undefined/{id}' value and findAll method having four properties i.e. arguments,caller,length and name having a value null, null, 0 and "" respectively

I have checked my url of model by navigating through localhost on browser and it is correct. Then why model cannot getting the values of json file?


Source: (StackOverflow)

autosuggestion is not working using canjs

I am trying to to create auto suggest element manually. I am using canjs for this prupose.

Following code I have tried so far:

list.filter( function( item, index, list ) {
   if(item.includes(searchText) && searchText != ''){
     //css hide and show classes for match
   }
   else{
      // css show for unmatched results
   }
})

In above code I am facing two problems:

  1. includes does not work in all browsers. For that I have tried match,
    contains and sub-string but they could not help me.

  2. includes working in chrome but when I entered the string whose substring is not contained by the last element of list it will not
    work because filter will keep searching from all the elements.

Is there any mistake I am doing?

I want to it to run in all the browser.

Thank you.


Source: (StackOverflow)

CanJS - Control Communication

I am learning CanJS now , so I want to try a very basic small demo. The demo is you will have different types of mobile recharge plans which displayed on the top (Radio buttons) and by choosing each plan the corresponding price options will be displayed in a table at the bottom.

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

For now I am directly calling the control method through its instance , but I am not sure if it is right way to do. Also please explain Can.Route.

Output 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's 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's 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 Call

new CategoryControl("#categoriesView");     

Source: (StackOverflow)

More restfunctions on canjs model

Is there a way to add more rest bindings on model then just the four CRUD functions?

var Customer = can.Model({
    findAll: 'GET /customer',    
    findOne: 'GET /customer/{id}',
    create: 'POST /customer',
    update: 'PUT /customer/{id}',
    destroy: 'DELETE /customer/{id}'
    //maybeAnOtherMethod: 'PUT /customer/{id}/activate'
}, {

});

Source: (StackOverflow)

How to Debug EJS code in Chrome/Safari

I am using EJS templates with CanJS and are looking for a way to debug my EJS code. Currently firebug can show me the syntax errors in EJS but in other browsers, I am not able to see anything.I need to go through my EJS file very carefully to solve the errors. I searched on web and found out about ejs_fulljslint https://code.google.com/p/embeddedjavascript/ , but not able to run this properly. I included the script into my HTML file but still wasn't getting any console errors. I am not able to find a demo of debugging on web.

Can anyone tell me how to debug my EJS code. If you can provide me any example, that will be highly appreciated.


Source: (StackOverflow)

CanJS Model findAll returns list of duplicate items

I'm using can.Model to retrieve data by id:

Invoice = can.Model({
    findAll: 'GET /invoices',
    create  : "POST /invoices",
    update  : "PUT /invoices/{id}",
    destroy : "DELETE /invoices/{id}"
},{});

When navigating to /invoices, the result is as expected, like:

[
    0: {
         "ID": "1",
         "Client": "Client1",
    },
    1: {
         "ID": "2",
         "Client": "Client2"
    }
]

However, the data retrieved with Invoice.findAll and logged to the console, it looks like this, with the same data item repeated for each element in the list:

[
    0: {
         "ID": "1",
         "Client": "Client1"
    },
    1: {
         "ID": "1",
         "Client": "Client1"
    }
]

The response from the server is correct, so why is it being interpreted as a list of identical items?


Source: (StackOverflow)

CanJS Observable and dots in keys

My problem is while using canJS Observable I can't use dots in object keys, because can think that some nesting available here.

So let's say if I create new observable:

var obs = new can.Observe( { "div.test-class": { "color": "#000000;" } } );

can fails with message

can.Observe: Object does not exist

And I can't create observable using just

var obs = new can.Observe( { ".test-class": { "color": "#000000;" } } );

because now can fails with the following error:

TypeError: current._set is not a function

Creating observable using following code

var obs = new can.Observe( { "div": {}, "div.test-class": { "color": "#000000;" } } );

works perfectly but I DON'T NEED nesting, and can tries to nest test-class into div inside observable.

So, any thoughts how I can achieve what I need?


Source: (StackOverflow)

CanJS object list automatic subclassing and reclassing

A remote, third-party JSONP server provides my CanJS script with a list of results like this one:

[
    { "class": "ABaseClass", "value": "1"},
    { "class": "ASubClass", "value": "2"},
    { "class": "ABaseClass", "value": "3"},
    { "class": "ASubClass", "value": "4"}, 
    ...
]

where type is the intended object class, defined in CanJS using can.Model.extend:

The following simplified code demonstrates the CanJS setup:

ABaseClass = can.Model.extend({ ... }, {
    'findAll': { 'url': 'the url', 'dataType': "jsonp" }
    // this is modified source code and may not run
});

// ASubClass is a subclass of ABaseClass.
ASubClass = ABaseClass.extend({ ... }, { ... });

Problem:

When ABaseClass.findAll({}, function(data) { ... }) is called, which calls the JSONP endpoints for more objects, the callback obtains a list of CanJS models, but only of class ABaseClass.

Question:

Is there a helper method provided by CanJS to automatically create subclasses based on a field within a list of objects? If not, how can I go about implementing one?


Expected output:

[
    (new ABaseClass(...)),
    (new ASubClass(...)),
    (new ABaseClass(...)),
    (new ASubClass(...)),
    ...
]

Environment:

  • CanJS: 1.17
  • jQuery: 1.10.1
  • I cannot control what types of objects the endpoint returns.
  • Multiple AJAX calls is not an accepted solution.

Source: (StackOverflow)

The best way to show loader message during model.list loading

I created a simple MVC application with canjs for an users list, by using can.Model.List. Since my request could take more than 5 second, I would add in the view a little preload message/image during the loading.

i.e. I would something like this (I'm using mustache)

var users = new Users.List({});
element.html(can.view('myView', users);

with this template:

{{#if loading}}
   <p>Loading, please wait...</p>
{{else}}
   <ul>
      {{#each this}}
         <li>User {{ name }} {{ surname }}</li>
      {{/each}}
   </ul>
{{/if}}
</ul>

I can solve by having a new observable variable, but I think there's a better way to direct manage this deferred data inside the view.

Any ideas?


Source: (StackOverflow)

Canjs – When to use which mustache tag when iterating lists?

There seems to be a few different ways to do the same thing in Can.js, which is great! But some of the ways work a little differently than others, and can affect how the DOM is rendered and updated. I'd appreciate it if someone could clear up the nuance.

I think the scenario where this choice becomes interesting is when you want to have some default text or a placeholder for an empty list.

{{#if list}} and {{#if list.length}}

These are not the same. Both an empty array and a can.List will render for {{#if list}}.

fiddle

{{#each list}}

So using what we learned with #if...

{{#if list.length}}
   <ul>
      {{#each list}}
         <li>...<li>
      {{/each}}
   </ul>
{{else}}
   <i>The list is empty.</i>
{{/if}}

{{#list}}

I think this is intended to be the best of both worlds. It only occurred to me today that since this is a block helper, it supports the {{else}}.

{{#list}}
   rendered for each item in list
{{else}}
   rendered once if list is empty
{{/list}}

The thing is, this can't produce the html we did with #each.

  • Wrap the whole thing in a <ul> tag, it gets rendered regardless of the list being empty or not
  • Stick the <ul> tag in the first block (positive block? affirmative?) and it renders every time

So the implementation seems to be dependent on the markup. Fair enough.

Here's the rub.

Supposedly, #each and #list update the DOM differently. From the docs for #each...

If the value of the key is a can.List, the resulting HTML is updated when the list changes. When a change in the list happens, only the minimum amount of DOM element changes occur.

So add one item to the list, only that item is rendered, remove an item, only that element is removed. The behavior of #list is not documented, but I'm under the impression it may re-render the entire block.

Questions

Which is best? Besides being more terse, I'm not sure #list has any advantages, so why do the authors suggest that it is preferred?


Source: (StackOverflow)

Canjs - Extending can.Model with additional Methods

I'm not the first person to ask this... the answers basically say "Well you're doing REST wrong." Fair enough, but development is filled with tradeoffs and I often find myself not in a position to rewrite the API.

Moving on to the problem at hand, what's the most elegant way to add a method for some resource to a model?

var Issue = can.Model.extend({
  findAll: 'GET Issues',
  findOne: 'GET Issues/{id}',
  findRelated: can.Model.makeFindAll(function(params) {
    return can.ajax({
      type: 'GET',
      url: 'Issues/'+params.id+'/'
    });
  })
},{});

jsfiddle


Source: (StackOverflow)

Canjs Not Routing

so this bug is killing me as I have no clue what's going on, I updated my canjs version to the latest which is currently 2.0.4 with jquery, and the router stopped working. Is not routing anything, I try with window.location.hash and can.route.attr and is not routing. The thing that bugs me is that with the old version I had was working perfectly. Here is the code

var Router = can.Control({
    'init': function() {
    },
    'route' : function(){
        window.location.hash = '#!dashboard';
    },
    'dashboard route': function() {
        console.log('dashboard')
    }
});

$(document).ready(function() {
    can.route.ready(false);
    new Router($('body'));
    can.route.ready(true);
});

Source: (StackOverflow)

CanJS models: attr function and nested data

In canJS I can set a model property with person.attr('name', 'John Doe');, but sometimes that property contains nested data, so I need to do the following:

var address = person.attr('address');
// Update country
address.country = 'USA'; 
person.attr('address', address);

Is there a shorter solution for this in canJS?


Source: (StackOverflow)