I am using i18n-js to load locales in to my js app. When I use the translate function in my view I would like to be able to just say t('Hello') instead of I18n.t('Hello'). How can I get such an alias to work?
import I18n from 'i18n';
const Hello = () => {
return (
<div>{I18n.t("hello", {name: "John"})}</div>
)
}
You could assign the t function to window:
window.t = I18n.t;
Then you can just use t('Hello'). However, as #Thilo mentioned, this may result in some complications.
A better alternative is to write a small wrapper:
function t(key){
return I18n.t(key);
}
The best option, suggested by #deceze, would be this single line:
var t = I18n.t.bind(I18n);
Single-line, and should work regardless of the scope it's called in.
Related
I know how this works in C#, however not so much in javascript so I am hoping it is similar.
With Javascript can I create say a master.js, with a variable (var defaultValue = "1234"), which I can reference in all other javascript files associated with the project?
so in terms of Lightswitch HTML, each screen has the ability to have a js file, and on the screen I want to be able to retrieve this defaultValue.
Can this be done?
If yes, how can I get this value onto the current screen?
so far I have created a main.js file, added this function:
function getDefaultValue(value) {
var value = "1234";
return value;
}
and declared the js file in the default.htm file:
<script type="text/javascript" src="Scripts/main.js"></script>
I know this is how i am using other JavaScript files like blob.js, lsWires.js etc...
using this method in by screen.js doesn't work so one of these stages is causing an error...
window.alert(main.getDefaultValue(value));
ideally i would like to use this defaultvalue for setting a value, i.e. var test = main.getDefaultValue(value)
This is certainly possible, and the script declaration you've used in your default.htm appears correct.
However, as the approach you've described creates a global getDefaultValue function (added to the global window object context) you wouldn't specify a main 'namespace' prefix like you would in c#.
Instead, rather than calling the function using main.getDefaultValue, you'd use the the following approach within your LightSwitch screens:
myapp.BrowseProducts.created = function (screen) {
window.alert(window.getDefaultValue("123")); // This will display 1234
// As window is a global object, its window prefix can be omitted e.g.
alert(getDefaultValue("123")); // This will display 1234
};
Or, if you want to define a global defaultValue variable in your main.js (probably the approach you're looking to implement) you would have the following code in your main.js file:
var defaultValue = "5678";
Then you'd access it as follows in your LightSwitch screens:
myapp.BrowseProducts.created = function (screen) {
alert(defaultValue); // This will display 5678
defaultValue = "Hello World";
alert(defaultValue); // This will now display Hello World
};
Also, if you'd like to organise your functions/properties in a main 'namespace', you could use the following type of approach in your main.js file: -
var main = (function (ns) {
ns.getDefaultValue = function (value) {
var value = "1234";
return value;
};
ns.defaultValue = "5678";
return ns;
})(main || {});
These would then be called as follows in your LightSwitch screens: -
myapp.BrowseProducts.created = function (screen) {
alert(main.getDefaultValue("123")); // This will display 1234
alert(main.defaultValue); // This will display 5678
main.defaultValue = "Hello World";
alert(main.defaultValue); // This will now display Hello World
};
This type of approach is covered in the following posts: -
How to span javascript namespace across multiple files?
JavaScript Module Pattern: In-Depth
I have been creating my own library for a custom layout script. For ease of use, I am trying to emulate how jQuery exposes its library through the jQuery() which makes the code very easy to read and straightforward. I have come up with something that works but I am not sure if this is the correct way to do this. Rather than keep the functions internal all the functions are "appended" to the library. Anyways, the code which works for me so far is as follows:
slateUI = (function(slateID){
slateUI.ID = slateID;
return slateUI;
});
and a related function looks something like this:
slateUI.doSomething = function(content)
{
//DID SOMETHING USING slateUI.ID
}
I am fairly new to OOP like features of the language. I am sure there is a better way to approach this. The issue that I have is handing down the Element to an appened function call so for instance:
slateUI("#someSlate").doSomething(...)
Obtains its element from the slateUI.ID
Is this the correct way to approach this? Or is this a hacked way that I came up with and there is some straight forward way to do this?
// function which returns a new SlateUI object (so we dont have to use the "new" keyword)
slateUI = function ( slateID ) {
return new SlateUI( slateID );
};
// class definition
function SlateUI ( slateId ) {
this.id = slateId;
}
// methods added to the class prototype (allows for prototypical inheritance)
SlateUI.prototype.someFunction = function() {
alert( this.id );
return this; // adding this line to the end of each method allows for method chaining
};
// usage
slateUI( 'someid' ).someFunction();
The short version of your question is that you're looking for the ability to chain your functions.
This is achieved simply by returning the relevant object from each function. If the function has no other return value, then just return the this variable, to pass control back to the caller.
I want to use an initialization function that will be called after a user visits a part of the application, but after that first visit I don't want to initialize anymore. A simple way to do this is using a flag and an if-statement, but there is a nicer solution to this problem:
in other languages I changed the body of the init function so that after the call of this method.
Can this be done in Javascript too? I wrote something like this, but eclipse says that it is an illegal assignment:
function initEdit(){
...
this = function() {};
}
Yes, you can, but this doesn't refer to the function, so you have to specify it by name:
function initEdit(){
...
initEdit = function() {};
}
Another alternative, that might be easier to follow, is to just use a variable:
var initialised = false;
function initEdit(){
if (!initialised) {
initialised = true;
...
}
}
I'm using Jasmine and have a library js file with lots of functions which are not associated with any object (i.e. are global). How do I go about spying on these functions?
I tried using window/document as the object, but the spy did not work even though the function was called. I also tried wrapping it in a fake object as follows :
var fakeElement = {};
fakeElement.fakeMethod = myFunctionName;
spyOn(fakeElement, "fakeMethod");
and test with
expect(fakeElement.fakeMethod).toHaveBeenCalled();
This does not work either as the spy did not work.
If you are defining your function:
function test() {};
Then, this is equivalent to:
window.test = function() {} /* (in the browser) */
So spyOn(window, 'test') should work.
If that is not, you should also be able to:
test = jasmine.createSpy();
If none of those are working, something else is going on with your setup.
I don't think your fakeElement technique works because of what is going on behind the scenes. The original globalMethod still points to the same code. What spying does is proxy it, but only in the context of an object. If you can get your test code to call through the fakeElement it would work, but then you'd be able to give up global fns.
TypeScript users:
I know the OP asked about javascript, but for any TypeScript users who come across this who want to spy on an imported function, here's what you can do.
In the test file, convert the import of the function from this:
import {foo} from '../foo_functions';
x = foo(y);
To this:
import * as FooFunctions from '../foo_functions';
x = FooFunctions.foo(y);
Then you can spy on FooFunctions.foo :)
spyOn(FooFunctions, 'foo').and.callFake(...);
// ...
expect(FooFunctions.foo).toHaveBeenCalled();
There is 2 alternative which I use (for jasmine 2)
This one is not quite explicit because it seems that the function is actually a fake.
test = createSpy().and.callFake(test);
The second more verbose, more explicit, and "cleaner":
test = createSpy('testSpy', test).and.callThrough();
-> jasmine source code to see the second argument
A very simple way:
import * as myFunctionContainer from 'whatever-lib';
const fooSpy = spyOn(myFunctionContainer, 'myFunc');
Solution with TypeScript
Replace your import:
import { yourGlobalFunction } from '../your-global-functions';
with:
import * as Functions from '../your-global-functions';
Then:
spyOnProperty(Functions, 'yourGlobalFunction').and.returnValue(() => 'mock return value');
import * as saveAsFunctions from 'file-saver';
..........
.......
let saveAs;
beforeEach(() => {
saveAs = jasmine.createSpy('saveAs');
})
it('should generate the excel on sample request details page', () => {
spyOn(saveAsFunctions, 'saveAs').and.callFake(saveAs);
expect(saveAsFunctions.saveAs).toHaveBeenCalled();
})
This worked for me.
The approach we usually follow, is as follows:
utils.ts file for all global utilities:
function globalUtil() {
// some code
}
abc.component.ts:
function foo {
// some code
globalUtil(); // calls global function from util.ts
}
While writing a Jasmine test for function foo (), you can spy on the globalUtil function as follows:
abc.component.spec.ts:
import * as SharedUtilities from 'util.ts';
it('foo', () =>
{
const globalUtilSpy = jasmine.createSpy('globalUtilSpy');
spyOnProperty(SharedUtilities, "globalUtilSpy").and.returnValue(globalUtilSpy);
foo();
expect(globalUtilSpy).toHaveBeenCalled();
});
My answer differs slightly to #FlavorScape in that I had a single (default export) function in the imported module, I did the following:
import * as functionToTest from 'whatever-lib';
const fooSpy = spyOn(functionToTest, 'default');
I guess it's the easiest way:
const funcSpy = spyOn(myFunc, 'call');
We are starting a new project and we have decided to use javascript ""namespaces"" to organize our client side code. The thing is that we have noticed that we can end very easily with super-long namespaces that are dificult to remember like
myProject.components.myComponent.doSomethig();
Is there any better way to do this or create some kind of "alias" somehow?
Thanks.
In JavaScript, you can make shortcut references to long namespaces stuff
var myComp = myProject.components.myComponent;
myComp.func1();
This is a reference only. You can do this with other long names and write less like this
var getEl = document.getElementById,
myEl = getEl('divId');
Also you can organize your code with RequireJS to organize your code
// file: myProject/components/myComponent.js
define(function(){
var myComponent ={};
myComponent.func1 = function(){
...
}
return myComponent;
});
// file: myProject/main.js
require(['myProject/components/myComponent', 'myProject/components/myComponent2'],
function(comp1, comp2){
var main = {};
main.init = function() {
...
comp1.func1();
}
});
// file: myProject/index.html
<script src="libs/require.js" data-main="myProject/main"></script>
If you use scoping functions around your module code (and if you don't, you should), then you can create local aliases quite easily as variables shared by all of the functions within a given module.
E.g., code defining the myComponent component:
(function() {
var comp = {};
// Export our component
myProject.components.myComponent = comp;
// add things to `comp`; since `comp` and `myProject.components.myComponent`
// refer to the same object, adding to `comp` is adding to the one object
// they both refer to and so you can access those things via either reference
})();
Similarly if you're writing app code that uses multiple components:
(function() {
var thisComp = myProject.components.thisComponent,
thatComp = myProject.components.thatComponent;
// Use `thisComp` and `thatComp`
})();
You can always store a subnamespace in a local variable:
var myComponent = myProject.components.myComponent;