I am working on an old code base which uses dojo datagrid and JsonRestStore, using declarative approach(in HTML). I am now trying to adapt this to use the newer dojo.store.JsonRest .
When I declare the JsonRest and ObjectStore in HTML, it works.
I want to use json.store.Cache as my store, with dojo.store.JsonRest and dojo.store.Memory backing it.
The constructor for json.store.Cache takes two arguments.
a) Is there a possibility to define constructor arguments in HTML declarative style?
I didn't want to touch the (declarative) code of the Datagrid so I tried setting the store of the Grid in dojo.addOnLoad . I get a weird error in Firebug for dojo.js line 402 which is actually a comment:
// 5. Evaluated: the module was defined via define and the loader has evaluated the factory and computed a result.
My guess is that the error has nothing to do with dojo.js at all and the exception actually occurred in a closure somewhere(I think I've seen this before).
b) Is it possible to mix and match Declarative and Programmatic style in this way? And if yes, what event should I be setting the grid's store on?
I'm answering this myself as I figured it out later. There seems to be no problem in mixing and matching the declarative and programmatic style.
I changed from using dojo.addOnLoad to dojo.ready , but I don't think that was the problem anyway.
I was trying to set the datagrid's query in a call to datagrid.setQuery and then setting the store with datagrid.setStore. It didn't work no matter which order I tried in(query first or store first).
Turns out both have to be set together in the call to setStore. The method accepts the query as its second parameter.
This solved my problem.
Related
I've been working a personal Vue project that includes a simple Google map.
While implementing the Maps JS API, I annoyingly kept encountering the ESLint error 'map' is assigned a value but never used. I understand why I'm getting this error—The Map() constructor returns a value that I don't need to do anything with:
const map = new google.maps.Map(el, options)
So I eventually just implemented the solution described in this Stack Overflow answer to bypass the lint rule.
If you're using a poorly designed library where the class constructor has side effects (which it isn't supposed to), and you don't need to do anything with the returned value from the class, I would disable that specific eslint rule for those lines.
However, my question is, why is Google's Map() constructor designed in this way? I have a hard time believing this library would be "poorly designed" but can't see a reason for this implementation.
It not side effect. It's returning instance of it. So you can call further methods on it
This question has less to do with how to do something, but more about best practices and what do others do?
I have a few services where I am using some kind of an external API (in this case the session storage api in the browser), where I am reusing the same constant string, the name of the company and the application, let's call it "ACME.Storage.", and this I want to prepend at the start of every "key" string. I see my options as:
I can just reuse the string "ACME.Storage." in every call.
I can create a JavaScript function where I create a new storage object that is configured with "ACME.Storage." once. That way, "ACME.Storage." appears once in my code.
I can create a local variable ans store "ACME.Storage." in it, then reuse that. Again, the string literal appears only once in my code.
I can create a separate javascript object that I can share.
I can use an AngularJS "constant"
I can add as a field to the app of config file.
I can store it somewhere where localized literal strings (even though this particular string isn't localized) and get it through a translation service.
I'm leaning toward using the "constant" service 'cause it's the one that's easily injectable. My only concern is that it's less encapsulated than some of the other options.
Opinions on the best practice?
To expand upon what Whishler posted, you can (and probably should) use the Constant module that Angular provides. Complete docs are found here: http://docs.angularjs.org/api/ng/type/angular.Module. Services are a common place for constants, but the Constant modules get applied before other provide methods. Another option would be Value, but it does pretty much the same thing.
Generally, I put constants into a service.
Depending what I'm doing, I may create a service that does nothing but store related constants. Or I may add them to another service representing a 'model'.
I'll also add that JavaScript doesn't officially have constants; so unless you wrote some code--such as your own accessors--you're just dealing with a variable that could be changed during the execution.
I am working on a project with a lot of user-generated code(inspired by this video http://vimeo.com/36579366). What I want to do is to eval() a chunk of user-input code, and run a function every time a var is defined, or 2 variables are multiplied, or some other action occurs.
Is there a way to do this in JS?
Obviously, I could search the field for "var ..." and then read what comes next, and then do whatever I need to do with that information, but, for a number of reasons, I would rather do it "legitimately" where I actually react to something being executed.
You can use the Intercession API in certain versions of Javascript (also known as proxies). From this you can redefine what happens when objects mutate by writing your own code.
If that's not possible, but you know the names of the variables in advance, you can use setters, getters, or a polyfill for Object.watch to achieve the same effect.
If you don't know what the variable names are going to be, I recommend running the user-defined Javascript through a parser like Esprima to obtain an AST. From this you can inject arbitrary syntax directly into the AST when you see variables being defined (or hoisted), and then compile back to working code. You'll be looking for JSON objects with "type": "VariableDeclaration".
I have a web application based on apache. php, js and jquery. All works fine.
On the client side there is a small library in JS/jquery, offering some generic list handling methods. In the past I used callbacks to handle those few issues where those methods had to behave slightly different. That way I can reuse methods like list handling, dialog handling and stuff for different part of the application. However recently the number of callbacks I had to hand through when stepping into the library grew and I am trying a redesign:
Instead of specifying all callbacks as function arguments I created a central catalog object in the library. Each module of the application registers its own variant of callbacks into that catalog upon initialization. At runtime the methods lookup the required callbacks in that catalog instead of expecting it specified in their list of arguments. This cleans up things quite a lot.
However I have one thing I still cannot get rid of: I require a single argument (I call it context, mode might be another term) that is used by the methods to lookup the required callback in the catalog. This context has to be handed through to all methods. Certainly better than all sorts of different callbacks being specified everywhere, but I wonder if I can get rid of that last one to.
But where do I specify that context, if not as method argument ? I am pretty new to JS and jquery, so I failed to find an approach for this. Apparently I don't want to use global vars, and to be frank I doubt that I can simply store a context in a single variable anyway, since because of all the event handlers and external influences methods might be called in different contexts at the same time, or at least interleaving. So I guess I need something closer to a function stack. Maybe I can simply push a context object to the stack and read that from within the layers of the library that need to know ? The object would be removed when I leave the library again. Certainly other approaches exist too.
Here are so many experienced coders how certainly can give a newbie like a short hint, a starting point that leads to an idea, how to implement this. How is such thing 'usually' done ?
I tried round a while, exploring the arguments.callee.caller hierarchy. I thought maybe I could set a prototype member inside a calling function, then, when execution steps further down I could simply traverse the call stack upwards until I find a caller holding such property and use that value as context.
However I also saw the ongoing discussions that reveal two things: 1.) arguments.callee appears to be depreciated and 2.) it appears to be really expensive. So that is a no go.
I also read about the Function.caller alternative (which appears not to be depreciated and much more efficient, however until now I failed to explore that trail...
As written currently passing the context/mode down simply works by specifying an additional argument in the function calls. It carries a unique string that is used as a key when consulting the catalog. So something like this (not copied, but written as primitive example):
<!-- callbacks -->
callback_inner_task_base:function(arg1,arg2){
// do something with args
}
callback_inner_task_spec:function(arg1,arg2){
// do something with args
}
<!-- catalog -->
Catalog.Callback:function(context,slot){
// some plausibility checks...
return Catalog[context][slot];
}
Catalog.base.slot=callback_inner_task_base;
Catalog.spec.slot=callback_inner_task_spec;
<!-- callee -->
do_something:function(arg1,arg2,context){
...
// callback as taken from the catalog
Catalog.Callback(callback,'inner_task')(arg1,arg2);
...
}
<!-- caller -->
init:function(...){
...
do_something('thing-1',thing-2','base');
do_something('thing-1',thing-2','spec');
...
}
But where do I specify that context, if not as method argument ?
Use a function property, such as Catalog.Callback.context
Use a monad
I have a ajax form that populates select lists with values based on the previous selected select list item. This form is used in 3 different views with each view adding an extra select list. I have written some basic validation code that keeps the form process in sync and doesn't confuse the user.
I have written one function that handles all 3 forms in an external script file.
My Question:
Is it acceptable or is there anything I need to worry about if some of my variables are undefined based on the form and view?
Here is some sample code that illustrates my question:
Note: These are not the actual names of my variables.
(function ($){
var objects = {sl1:$('#SelectList1'),sl2:$('#SelectList2'),sl3:$('#SelectList3'),lbl1:$('#Label1'),lbl2:$('#Label2'),lbl3:$('#Label3')};
objects.sl1.change(function(){
mapValues();
}
function mapValues(){
objects.lbl1.text(objects.sl1.val());
objects.lbl2.text(objects.sl2.val());
objects.lbl3.text(objects.sl3.val());//What if this select list is undefined for View1?
}
})(jQuery);
To summarize, View #1 has SelectList1 & SelectList2. View #2 has all 3. Is there a performance issue or is it bad practice to call a function where some of the variables are undefined?
Thanks.
This is more of a jQuery issue, not a JS one. jQuery simply does nothing (it does not even fail!) if you execute a method such as .text() or .val() on an empty result from a selector. For the performance issue, test it yourself. If the element is not found, I expect the performance to be a little better compared to when an element exists.
So, it's valid to use such code.
Note that you're mixing up "undefined variables" with "non-available elements" which are totally different matters. Using undefined variables is strongly discouraged and often lead to unexpected behavior.
I think it's more about readability and maintainability at this point. I mean would it be clear to another developer just by looking at your JS that View #1 has SelectList1 & SelectList2 ? Looking at the code you would think it has all three since all the forms use the same JS. Maybe making it more flexible to where individual forms can specify which selectLists are contained within the respective form, this way the global script is only using the selectLists specified in the forms and not assuming all at available.
Yes it is bad practice. And is source of bugs.
For good practice, define default value, and/or check for it in your function.
thats why you should use the || operator
e.g. :
( $('#SelectList1').length || '0')
The issue is that you will introduce a level of uncertainty, and hence hard to trace bugs, if you do so. Different JS parsers will respond differently - some are more forgiving and will do nothing, others will just crash. So right away you have potential cross-browser issues.
Further, as those variables get passed around inside your code, if you do not know their values, you'll have a difficult time predicting how the rest of your code will interact with them. So now you also have potential logic/program bugs.
So do yourself a favor and a) check that any required parameters are passed, and do some error handling if it is not and b) make sure optional parameters are handled as soon as you receive them (eg assign them a default value, make sure they don't get passed on to other functions if they are not defined, whatever is most appropriate for your application logic).