0

I am trying to make MVC structure of application in canjs. For that I am using requireJS to separate the code in different file.

I have searched in google and i am following this tutorial but in that tutorail I dont find to access module variables in different modules. therefore I am following this method to do so.

But I cannot achieve that. This is my code:

requirejsconfig.js file :

  requirejs.config({
   paths :{
    enforceDefine: true,
    waitSeconds : 0,
    jquery      : "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min", 
    main        : "view/main",
    player      : "view/player",
    PlayerModel : "/models/PlayerModel",
    hbs         : "/models/view/js/handlebars",
    fixture     : "/models/view/js/can.fixture", 
    can         : "/models/view/js/can.jquery"

 }
});

main.js :

require(["player"],function(player){
    player.PlayerModel();
 });

I want to use that model methods in my controller.

player.js :

 define(['PlayerModel'],function(){

     function PlayerModel(){   
        var Player = PlayerModel.Player;
         Players =can.Control({ defaults :{view:view/players.hbs' }},{
            init: function(){
                this.element.html(can.view(this.options.view, {
                    players: this.options.players
                }));
            }
      $(document).ready(function(){
        $.when(Player.findAll()).then(
         function(playersResponse){
            var players = playersResponse[0];      

            new Players('.players', {
                players: players
             });
         });
    });
  }
});

PlayerModel.js:

   define(function(){

        var Player = can.Model({
            findAll: 'GET /models/players.json',
            findOne: 'GET /players.json/{id}'
        });
        return {
            Player:Player
        }
    });

Every file is being loaded (saw in network tab-chrome devtools) but nothing is being populated in output.

Can anybody help me ? Thanks in advance!

Community
  • 1
  • 1
Dipesh Raichana
  • 1,008
  • 3
  • 18
  • 36

2 Answers2

2

Carrying on with what @ekuusela said, restructure the code in Player.js in this format:

define(['PlayerModel'],function(){
  function PlayerModel(){ ... }
  return {
    PlayerModel: PlayerModel
  }
});

What's happening

Internally, two conventions are followed when defining modules. These relate to:

  1. What the module is called (its label)
  2. What this label represents.

Labeling Modules

The filename is taken as the module's name (unless shim is used, like you have). In other words, the define(['Module_Name'] ...), which is how I would normally read that line, can more accurately be read as a define(['Module_Path_Or_Shim_Symbol_Name' ...)

What Is This 'Module' Anyway

A module isn't magic - it is just a specially labeled map to a function. This map is maintained by RequireJS and probably looks similar to this:

var ModuleMap = {
  'Player' : function (...) { ... },
  'PlayerModel' : function (...) { ... }
};

Every time a module is accessed, through a require or define call, this map is accessed, and the relevant function found. However, that isn't enough - what we want is the stuff that is defined within the function - the fundamental concept of modules is that everything inside them has Module Function Scope, and is not exposed outside. So, to gain access to this "stuff", the RequireJS brain does the only thing it can do with a function - execute it.

var playerReference = require('Player');

Note that I've used the CommonJS notation of requiring modules, which is more readable for our current purpose.

So, in the code you posted, the module function has defined and declared PlayerModel as a function, but has not exposed it. Since the line player.PlayerModel() expects the module to return an object with a property named PlayerModel that refers to your function, the logical return value of the module is:

var exposedModuleReference = { PlayerModel: PlayerModel };
return exposedModuleReference;

Note that this means the name with which the function is exposed can be different from the function name itself. For example, the following code will also work without any changes anywhere else:

define(['PlayerModel'],function(){
  function PlayerModelConstructor(){ ... }
  return {
    PlayerModel: PlayerModelConstructor
  }
});

An Interesting Addition

So, executing a module function and assigning that return value to a reference is one part of what RequireJS's brain does. The other part is, it then updates this map so it now looks like this:

var ModuleMap = {
  'Player' : { PlayerModel: PlayerModelConstructor },
  'PlayerModel' : function (...) { ... }
};

This means that code written in module functions gets executed at most one time.

Sharadh
  • 1,298
  • 9
  • 15
  • thanx for clear my concept over modules. It is very clear and helpful answer.I am appreciate for this answer!! Thnx once again.!! – Dipesh Raichana Apr 17 '15 at 04:37
1

You define the function PlayerModel inside player.js and then require a module called PlayerModel there but don't assign the required module to any variable. You should first clean up your code, possibly rename some of your modules and move functions around.

Here, you try to access the function PlayerModel in the module player, but the module factory function in player.js doesn't return anything:

require(["player"],function(player){
   player.PlayerModel();
});

What gets assigned to the function parameter player is only whatever you return from the function that defines the module. (If you would define a module as an object then that object would be the argument.)

ekuusela
  • 5,034
  • 1
  • 25
  • 43