How to simplify this switch statement (Angular app) - javascript

I'm using a modalService to store modal templates in my mainController.
Here is how I store them (from mainController)
// Store popup modal:
$ionicModal.fromTemplateUrl('app/popup/popup.html', {})
.then(function(modal) {
PopupFactory.storeModal(modal);
});
// Store addTicker modal:
$ionicModal.fromTemplateUrl('app/tickers/addTicker.html', {})
.then(function(modal) {
ModalFactory.storeModal('addTicker', modal);
});
modalFactory
This is what the storeModal function looks like:
function storeModal(type, modal) {
switch(type) {
case 'addTicker':
vm.addTicker = modal;
break;
case 'addTag':
vm.addTag = modal;
break;
}
}
^ as you can see I have to create an object for each modal my app will have.
This is what the getModal function looks like:
function getModal(type) {
switch(type) {
case 'addTicker':
return vm.addTicker;
break;
case 'addTag':
return vm.addTag;
break;
case 'anotherModal':
return vm.anotherModal;
break;
case 'yetAnotherModal':
return vm.yetAnotherModal;
break;
}
}
I feel like this code can be optimized to 1 or 2 lines...
I've tried the follow to no avail:
function getModal(type) {
return vm.+type;
}
and
function getModal(type) {
var returned = type;
return vm.returned;
}
However when I call getModal in the respective Directive Controllers, I get undefined:
function addTickerButton() {
vs.addTicker = ModalFactory.getModal('addTicker');
vs.addTicker.show('addTicker);
$rootScope.$emit("modal.add.tickers");
}

You got very close here:
function getModal(type) {
var returned = type;
return vm.returned;
}
But you are trying to access a returned attribute on vm, which doesn't exist. To retrieve an attribute using a variable, you must use bracket notation:
function getModal(type) {
return vm[type];
}

Just do
function getModal(type) {
return vm[type];
}

What you need is an object accessor with bracket notation:
vm[type] = modal
See this link for more details.

Related

How do i exclude namespace functions when iterating over an enum?

I have the following code
export enum JournalEntryType {
ORDINARY_JOURNAL_ENTRY = 'ORDINARY_JOURNAL_ENTRY',
PLANT_TRANSPLANTED = 'PLANT_TRANSPLANTED',
SOW_SEEDS = 'SOW_SEEDS',
SEEDS_GERMINATED = 'SEEDS_GERMINATED',
PLANT_BLOSSOMS = 'PLANT_BLOSSOMS',
FRUIT_SETTING = 'FRUIT_SETTING',
FRUIT_CHANGED_COLOR = 'FRUIT_CHANGED_COLOR',
HARVEST = 'HARVEST',
ANIMAL_SIGHTING = 'ANIMAL_SIGHTING'
}
export namespace JournalEntryType{
export function getJournalEntryTypeColor(journalEntryType: string): string{
switch(journalEntryType){
case JournalEntryType.ORDINARY_JOURNAL_ENTRY.toString(): return '#FFFFFF';
case JournalEntryType.PLANT_TRANSPLANTED.toString(): return '#8B4513';
case JournalEntryType.SOW_SEEDS.toString(): return '#D2691E';
case JournalEntryType.SEEDS_GERMINATED.toString(): return '#7CFC00';
case JournalEntryType.PLANT_BLOSSOMS.toString(): return '#FFB6C1';
case JournalEntryType.FRUIT_SETTING.toString(): return '#FF69B4';
case JournalEntryType.FRUIT_CHANGED_COLOR.toString(): return '#ff1493';
case JournalEntryType.HARVEST.toString(): return '#DC143C';
case JournalEntryType.ANIMAL_SIGHTING.toString(): return '#800080';
default: throw new Error();
}
}
}
When i iterate over JournalEntryType and log every value like so:
for(let journalType in JournalEntryType){
console.log(journalType);
}
The last value that is printed won't be ANIMAL_SIGHTING but getJournalEntryTypeColor. In other words, it also iterates over any functions that are declared in the namespace. How do i prevent this from happening? I've tried filtering out the method with an if statement that checks whether the type of the journalTypeis a string. But that won't stop from getJournalEntryTypeColor getting printed as well.
The key thing is that you need to check the type of the property on the object, not the type of the key.
Object.keys(JournalEntryType)
.filter(journalType => !(typeof(JournalEntryType[journalType]) === 'function'))
.forEach(journalType => {
//code here
});
(This code is taken from the comments, it was written by Maurice.)

How to set value not contained in map with RxJS?

I am just getting started with Angular 4, and have a project I've been working on that involves displaying data that is retrieved using a REST API. The data seems to be getting retrieved properly and the form getting populated correctly.
Now, one of the values returned from the API only contains a single character. I was hoping to override the setter method to expand that single character to a full string. I understand I could just change the call to return the full string, however the API is supporting by multiple front-ends and I was hoping to keep them consistent. This plunker should what I am hoping to do (without the REST API involved): Plunker example
When logging in the subscribe function of my project, fullStatus is not included:
this.service.get(id).subscribe(p => {
this.test = p;
console.log(this.test);
});
When adding the switch statement here, things work as intended, however I was hoping to have this logic be bundled into the Test class instead of the subscribe function.
this.service.get(id).subscribe(p => {
this.test = p;
switch (this.test.status) {
case 'A':
this.test.fullStatus = 'Active';
break;
case 'I':
this.test.fullStatus = 'Inactive';
break;
case 'N':
this.test.fullStatus = 'No Certificate';
break;
default:
this.test.fullStatus = '';
break;
}
console.log(this.test);
});
Is there a better way for me to handle this? Thanks in advance.
Can't you do a map of your results after the api call to include this fullStatus property?
In your service,
// assuming you have to convert the response to json
get(id) {
return this.http.get(<url-to-get>).map((res) => {
let test = res.json();
switch (this.test.status) {
case 'A':
test['fullStatus'] = 'Active';
break;
case 'I':
test['fullStatus'] = 'Inactive';
break;
case 'N':
test['fullStatus'] = 'No Certificate';
break;
default:
test['fullStatus'] = '';
break;
}
return test; // returns each response element with the new property 'fullStatus' added based on its 'status'
});
}
Then you can simply subscribe it in your component class. Hope it helps.
You can create a test class like test-model.ts :
export class Test {
prop1 = ''; // dummy property (you can define these according to your need
prop2 = '';
status: string;
fullStatus?: string; // optional
init(responseData: any){
this.prop1 = responseData.prop1 ;
this.prop2 = responseData.prop2 ;
this.status = responseData.status;
switch (responseData.status) {
case 'A':
this.fullStatus = 'Active';
break;
case 'I':
this.fullStatus = 'Inactive';
break;
case 'N':
this.fullStatus = 'No Certificate';
break;
default:
this.fullStatus = '';
break;
}
}
}
In the component:
import {Test} from './test-model';
export class TestComponent implements OnInit
{
test: Test = new Test();
constructor(private service: MyService){}
ngOnInit(){
this.service.get(id).subscribe(p => {
this.test.init(p);
console.log(this.test);
});
}
}

How do i call a function on a Service from a Controller, on AngularJS

I am trying to call a function on a Service from a controller, in order to update the theme on my website, depending on which provider's section of the site i am on.
My Service,
MyApp.service('ThemeService', function() {
var ThemeProvider = 1;
var ThemeArea = "NotSet";
this.SetVariables = function() {
switch (ThemeProvider) {
case 1:
default:
ThemeArea = "Themes/Default";
break;
case 2:
ThemeArea = "Themes/Provider2";
break;
}
return ThemeProvider;
};
return {
ThemeProvider: ThemeProvider,
getThemeArea: ThemeArea,
};
});
My Controller
$scope.loadData = function (input) {
ThemeService.ThemeProvider = 2;
ThemeService.SetVariables();
};
My idea is that inside the controller, the function "SetVariables" can be called after the "ThemeProvider" is set, to change the "ThemeArea", but i cant work out how to call the function "SetVariables" from my controller.
When i try, i get an error
TypeError: Object doesn't support property or method 'SetVariables'
You're not returning SetVariables, see at the bottom of your Service definition there's a return statement, it should contain everything you want to be accessible.
return {
ThemeProvider: ThemeProvider,
getThemeArea: ThemeArea,
SetVariables: SetVariables
};
First of all your service returns an object which does not have any property called SetVariables, that's why you get the error.Also this.SetVariables will be looking for ThemeProvider which is initialized in your service (var ThemeProvider = 1;) and not the value assigned from controller.
Your code should be looking like this:
Service:
MyApp.service('ThemeService', function() {
var _ThemeProvider = 1;
var _ThemeArea = "NotSet";
angular.extend(this, {
SetVariables,
setThemeProvider,
setThemeArea,
getThemeProvider,
getThemeArea
})
function SetVariables() {
switch (_ThemeProvider) {
case 1:
default:
_ThemeArea = "Themes/Default";
break;
case 2:
_ThemeArea = "Themes/Provider2";
break;
}
return _ThemeProvider;
};
function setThemeProvider(val) {
_ThemeProvider = val;
};
function getThemeProvider() {
return _ThemeProvider;
};
function setThemeArea(val) {
_ThemeArea = val;
}
function getThemeArea() {
return _ThemeArea;
}
});
Controller:
$scope.loadData = function(input) {
ThemeService.setThemeProvider(2);
ThemeService.SetVariables();
};

Javascript - evaluating parameter again

I would like to create a function "when", that will work as a normal command, or just a function, and will be able to re-evaluate its parameters.
for example:
when(k==0) {
do something;
}
or
when(k==0, function() {
do something;
});
The thing is, that k is now for example equal to 1, and this function needs to always re-evaluate k==0 to determinate if it changed to 0.
*I do not want to send k==0 as a string 'k==0'.
Is that possible? If so, how?
*This is an academic question, please don't explain why it is so very wrong to create this function.
something like this?
function when(condition, callback){ if (condition) callback() }
and call it like
var a = 0;
when(a == 0, function(){ console.log( "yeyyyy") } );
after reading the comments above
some kind of mechanism for observing when a variable's value changes
change when method to
function when(lhs, operator, rhs, callback)
{
var result = false;
switch( operator )
{
case "==": result = (lhs==rhs); break;
case "===": result = (lhs===rhs); break;
case "<": result = (lhs<rhs); break;
case ">": result = (lhs>rhs); break;
case "<=": result = (lhs<=rhs); break;
case ">=": result = (lhs>=rhs); break;
default: result = true;
}
if (result) { callback() }
else { setTimeout( function(){ when(lhs, operator, rhs, callback) }, 1000 ); }
}
What would work would be to use a lambda for both the condition and the action. Using arrow function expressions (thanks #Kyll), it's even reasonably compact.
when (() => k == 0, () => { do something; });

capturing function call as a string

using JS; I am passing a function name as an optional argument. I would like to make a switch case that reads the functions name that is being passed. How would I capture the functionVariable as if it were a string "functionVariable"?
Example:
function test(functionVariable)
{
switch(functionVariable)
{
case firstFunction:
alert('1st');
break;
case secondFunction:
alert('2nd');
break;
}
}
When I alert functionVariable, it prints the whole function. It makes sense why but I'm trying to work around it and just get the functions name.
EDIT
Working example
function test(functionVariable)
{
switch(functionVariable.name)
{
case firstFunction:
alert('1st');
break;
case secondFunction:
alert('2nd');
break;
}
}
You could use Function.name.
function doSomething() {
// does something
}
console.log(doSomething.name); // "doSomething"
Note that this only works for function declarations and named function expressions. Unnamed function expressions won't work.
var getA = function getA() {
};
console.log(getA.name); // "getA"
var getB = function() { // Notice the lack of a name
};
console.log(getB.name); // ""
You can use functionVariable.name, here is an example:
x = function test() {}
console.log(x.name)
// logs "test"

Categories

Resources