I am looking for a functionality like below in dojo class (AMD).
function () {
var _foo = 123; // private variable
return {
get foo () { return _foo; }
};
}());
The advantage is once the value _foo is initialised user can't modify the value _foo or foo from the console. How do we achieve this in dojo class like
define["dojo/_base/declare", "dojo/request", "dojo/_base/lang"],
function(declare, request, lang) {
var _foo = 123;
return declare("fooClass", null, {
get foo () { return _foo; }
});
});
when i declare as above when we try to build the class using dojo build.sh it is giving parsing errors.how to make a value not changeable from debug console in dojo
There is not really an advantage with your solution, as if an user open the debugger console, a developer could set a breakpoints at var _foo =123; and change its value at run time any time.
In your code actually you are showing an example of a closure.
A closure allow your var _foo to be hidden inside your function() so a developer would not be able to get that value within its js code.
Nevertheless you can still access it using the debugger console adding a simple breakpoint.
If you are interesting to use getter and setter for dojo, please read on.
The dojo naming convention to specify a custom getter or setter (in this example for an attribute named foo) is:
_setFooAttr() and _getFooAttr()
Example:
require([
"dojo/_base/declare", "dojo/dom-style", "dojo/parser", "dojo/ready",
"dijit/_WidgetBase", "dijit/_TemplatedMixin"
], function(declare, domStyle, parser, ready, _WidgetBase, _TemplatedMixin){
declare("HidePane", [_WidgetBase], {
// parameters
open: true,
// custom setter
_setOpenAttr: function(/*Boolean*/ open){
this._set("open", open);
domStyle.set(this.domNode, "display", open ? "block" : "none");
}
});
ready(function(){
parser.parse();
});
});
Related
I am trying to test a event in a Template. Within the click event, there is a Reactive Var that gets set.
The test is blocked by the Reactive Var.
Any ideas on how I stub or mock a reactive var in a template? I tried adding it to the template (template.reactiveVar = "whatever"), but no go, as I don't think it's writeable.
The ?? indicate where I am wondering what to put.
it('sets a reactive var when a button is clicked', function(){
Template.button.fireEvent('click ', {
context: { some: 'values'},
event: {'target': {'text': 'randomText' } },
templateInstance:new Template('upload', function(e) {
this.reactiveVar = new ReactiveVar("not clicked)
})
});
chai.assert.equal(Template.reactiveVar, "clicked")});
// The actual template is below..
Template.button.events{(
'click button': function(evt, template){
var text = evt.target.text
template.reactiveVar.set(text)
}
});
The result is...
TypeError: Cannot read property 'set' of undefined
Any ideas?
I suspect the event is actually firing and getting through to your event handler before the callback that creates the reactive var has run.
You should create the reactive var when you first create the template independent of your test:
Template.button.onCreated(function(){
this.reactiveVar = new ReactiveVar("not clicked");
});
I am trying to derive an "extended" Button from dijit/Form/Button. (I want to pass extra arguments to the constructor, and I want to encapsulate these preparations in my derived class. Button is just an example, I want to use this later with grids and trees.)
Unfortunately the code below fails with "TypeError: this._attachEvents is undefined" in the firefox javascript console. Some idea, what is wrong? The same code, including minimal HTML, is ready to run at http://jsfiddle.net/x9dLs8gz/1/
require(["dojo/_base/declare", "dijit/form/Button", "dojo/dom", "dojo/json", "dojo/domReady!"],
function (declare, Button, dom, json) {
declare("MyButton", Button, {
"-chains-": {
constructor: "manual"
},
constructor: function () {
//extra calculation will go here...
this.inherited(arguments);
}
});
new MyButton({
label: "Click Me!",
onClick: function () {
dom.byId("result").innerHTML += "Success";
}
}, "button").startup();
});
Cheers,
Dominic
If the "-chains-" value for the constructor method is either not set or set to "after", then the postscript method will be called after all of the inherited constructors have been fired. On the other hand, when specifying "manual", postscript is fired after the first constructor (in this case MyButton#constructor) is executed. As a result, _AttachMixins#buildRendering is fired before this._attachEvents has been set in _AttachMixins#constructor, causing the error you see.
Since specifying "manual" means that no chaining is assumed whatsoever, mixin contructors will never be called, even if this.inherited is correctly called up the chain. This makes sense, as the underlying C3MRO is thrown out the window.
If you need to continue using the "manual" setting in spite of this, you will need to 1) recreate any missing data yourself, 2) manually call the mixin constructors (e.g., _AttachMixin.prototype.constructor.call(this)), or 3) convert MyButton to a factory for Button:
var createButton = (function () {
var myButtonDefaults = { ... };
return function (kwArgs, id) {
var buttonId = id || 'button';
return new Button(lang.mixin({}, myButtonDefaults, kwArgs), buttonId);
};
})();
var myButton = createButton();
myButton.startup();
console.log(myButton instanceof Button); // true
You need to assign the declared class to a variable or declare in a different file and added it to the list of object in the require. Also dont use variable names which are keywords like "constructor". below is the fixed version of your example.
require(["dojo/_base/declare", "dijit/form/Button", "dojo/dom", "dojo/json", "dojo/domReady!"],
function(declare, Button, dom, json) {
var MyButton = declare("MyButton", Button, {
"-chains-": {
constructorType: "manual"
},
constructor: function() {
//extra calculation will go here...
this.inherited(arguments);
}
});
new MyButton({
label: "Click Me!",
onClick: function() {
dom.byId("result1").innerHTML += "Success";
}
}, "button").startup();
});
<div id="button"></div>
<div id="result1"></div>
i have a call back method which is called by other class when some event occurs, which send some objects as parameters
loadingIsDone : function(evt)
{
console.log(evt);
for(var i=0; i<evt.layers.length;i++)
{
var row = new _LayerRow(evt.layers[i].layer);
domConstruct.place(row.domNode,this.containerDiv,"last");
}
}
for each object which is received i need to create a Custom widget called _LayerRow, which is having one Checkbox and a Label
When i debug this code the pointer is not coming to the 2nd line of the loop.
and no error in the console..
but when i call the same in different file as below for testing purpose
var obj = new Object();
obj.id = "124";
obj.name = "Chiru";
var lay = new _LayerRow(obj);
domConstruct.place(lay.domNode,win.body(),1);
The _LayerRow widget is working fine
_LayerRow.js
define([
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_OnDijitClickMixin",
"dijit/_TemplatedMixin",
"dojo/text!../templates/_layerrow.html"
], function (declare, _WidgetBase, _OnDijitClickMixin,_TemplatedMixin, template) {
return declare([_WidgetBase,_OnDijitClickMixin, _TemplatedMixin], {
templateString: template,
layer : null,
constructor : function( layerObj)
{
this.id = layerObj.id;
this.layer = layerObj;
},
postCreate : function()
{
this.inherited(arguments);
this.layerName.innerHTML = this.layer.name;
}
});
});
and templates/_layerrow.html
<div>
<input type="checkbox" id="${id}">
<label for="${id}" data-dojo-attach-point="layerName"></label>
</div>
Any idea why its not working.. how can i find the issue in this
Most common reason for callbacks to fail is incorrect scope.
Because in asynchronous callbacks such as above, the context that the code is executing in has changed. It will no longer refer to the object that originally provided it, but its context will now refer to the enclosing object, the callback. To get around this, you can use hitch() to force the function to retain its original context
I see a reference to this in your callback, use hitch to correct the scope.
More info: http://dojotoolkit.org/reference-guide/1.9/dojo/_base/lang.html#hitch
Is there a way to have a static variable in a dojo (1.8) module so that I can retain state?
Example, say I set some value in some/module
require([
'some/module'
], function (module) {
module.setSomeValue(3);
});
.. and then want to retrieve it later
define([
'some/module'
], function(module) {
return {
start: function() {
var x = module.getSomeValue();
}
};
});
A solution that works but seems like a hack,
acompany = window.acompany || {};
acompany.project = acompany.project || {
};
require([
], function() {
var debug = false;
acompany.project.module = {
/* static variables and functions here */
};
});
define([
], function () {
return acompany.project.module;
});
Actually there is always only single instance of AMD module, because (source):
define has two additional important characteristics that may not be immediately obvious:
Module creation is lazy and asynchronous, and does not occur immediately when define is called. This means that factory is not executed, and any dependencies of the module will not be resolved, until some running code actually requires the module.
Once a module value has been entered into the module namespace, it is not recomputed each time it is demanded. On a practical level, this means that factory is only invoked once, and the returned value is cached and shared among all code that uses a given module. (Note: the dojo loader includes the nonstandard function require.undef, which undefines a module value.)
In addition you do not have to provide just factory function, you can provide an object literal as well:
define("some/module", {
someValue: "some",
otherValue: "other"
});
Then somewhere else in your code:
require(["some/module"], function(module) {
console.log("module.someValue", module.someValue); // some
module.someValue = "some changed";
});
require(["some/module"], function(module) {
console.log("module.someValue", module.someValue); // some changed
});
More robust solution includes an instance of dojo/Stateful, so you can watch for changes and define custom setters and getters:
define("some/stateful-module", ["dojo/Stateful"], function(Stateful){
var stateful = new Stateful({
someValue: "some",
otherValue: "other"
});
return stateful;
});
Then somewhere else in your code:
require(["some/stateful-module"], function(module) {
console.log("stateful-module.someValue:", module.get("someValue"));
module.watch(function(name, oldValue, newValue) {
console.log("stateful-module: property"
, name
, "changed from"
, "'" + oldValue + "'"
, "to"
, "'" + newValue + "'"
);
});
});
require(["some/stateful-module"], function(module) {
module.set("someValue", "some changed");
});
See how it works at jsFiddle: http://jsfiddle.net/phusick/fHvZf/. It's in a single file there, but it will work the same way across the whole application unless you require.undef(mid) the module.
There are multiple files in Dojo like dojo/date/locale that define static variables and functions and not widgets/classes using dojo.declare.
Define the module
define([
'dojo/_base/lang/',
'some/module'
], function(lang, module) {
var m = lang.getObject('some.module', true);
m.x = 0;
m.doSomething = function(){
// doSomething
};
return m;
});
Use the module
require([
'some/module'
], function(someModule) {
var debug = false;
/* someModule - static variables and functions here */
if(someModule.x == 0){
}
});
I'm new to dojo and can't figure out why this is happening
in dojo.html:
require(["dojo/query", "dojo/NodeList-dom", "dojo/domReady!", "a" ], function(query, a) {
query("#greeting").style("color", "red");
alert(a.sheep);
});
in a.js
define([], function() {
var a = {
"sheep": "blah",
}
return a;
});
Requiring and loading module a is fine, but when I try to alert a.sheep, I get undefined.
Note: I've also tried declaring sheep : "blah" as well and try changing sheep to an alert function and running a.sheep; which worked.
the reason you cannot access a.sheep is that there is dojo/NodeList-dom module in a variable. The order of elements in define/require array is bind to the list of arguments in the subsequent function. So you should write:
require(["dojo/query", "a", "dojo/NodeList-dom", "dojo/domReady!"], function(query, a) {
})
Also from the practical point of view I happen to format my code like this:
define([
"dojo/_base/declare",
"dojo/query",
"a",
"dojo/NodeList-dom",
"dojo/domReady!"
],
function(
declare
query,
a
){
return declare(null, {
constructor: function() {}
});
});
Every module on his own line, plus logical clustering of modules via empty lines.