I'm having trouble updating this code from angularjs ad angular 2, thank you for any help
if (settings != null && settings.checkSubscriptionForVip === true) {
return this.user.hasVipAccess().then(function(hasVipAccess) {
hasVipAccess ? deferred.resolve() : deferred.reject("NO_VIP");
return;
});
} else {
deferred.resolve();
return;
}
You neeed to have a boolean variable defined in your component and assign the result in to that,
hasVipAccess : boolean = false;
if (settings != null && settings.checkSubscriptionForVip === true) {
this.user.hasVipAccess().then(function(access) {
this.hasVipAccess = access;
});
} else {
this.hasVipAccess = access;
}
However if you do not need to set boolean variable, just return the result
Related
I'm trying to filter instructor_name but this table has many null values, how should I ignore those null fields and search/filter only from fileds which are not null
filter:
`item.instructor_name.toLowerCase().indexOf($scope.courses_search.toLowerCase()) != -1`
and because, there are many fields which are null Im getting an error
TypeError: Cannot read property 'instructor_name' of null
$scope.livesearch = function(item) {
if ($scope.courses_search == undefined) {
return true;
} else {
if (item.subject_cd.toLowerCase().indexOf($scope.courses_search.toLowerCase()) != -1 ||
item.acad_group.toLowerCase().indexOf($scope.courses_search.toLowerCase()) != -1) {
return true;
}
}
}
$scope.filterFunc = function() {
return function(item) {
if (item !== null && typeof item.class_instructor_name !== 'undefined') {
return item.class_instructor_name.toLowerCase().indexOf($scope.courses_search.toLowerCase()) != -1;
}
return false;
};
};
You are comparing item to null, but if item is undefined, the next validation will take place because (undefined !== null), so it will try to look up instructor_name on undefined, which obviously will not work.
AngularJS has it's own checkers, angular.isDefined() and angular.isUndefined(). You can use one of those, or do a slightly different check, such as:
if (item && item.instructor_name) ...
If you're using lodash, you can simply do:
if (_.get(item, 'instructor_name')) ...
One option is to add the filter on the controller and handle null checks from there.
Remeber to check if the value is defined before appling the toLowerCase() method.
$scope.filterFunc = function() {
return function(item) {
if (typeof $scope.courses_search !== 'undefined' && item !== null) {
if(typeof item.subject_cd !== 'undefined'){
return item.subject_cd.toLowerCase().indexOf($scope.courses_search.toLowerCase()) != -1;
}
if(typeof item.acad_group !== 'undefined'){
return item.acad_group.toLowerCase().indexOf($scope.courses_search.toLowerCase()) != -1;
}
}
return false;
};
};
Then in view
ng-repeat="item in items | filter:filterFunc"
I am looking for a possible solution to the below, I have an array that has an assigned watcher. My issue is changing the $scope after receiving a response from a http get request. $scope is always undefined, I need to change the value there in real time. Any suggestions would be greatly appreciated!
$scope.$watch('user.tags', function (newVal, oldVal) {to invalid until the
$scope.tags_valid = true;
// Loop through array and validate length
for (var i = 0; i < $scope.user.tags.length; i++) {
if ($scope.user.tags[i].data.length != 24) {
$scope.tags_valid = false;
return;
}
// Check if already exists
$http.get("api/registration/TagExists", { params: { Tag_Id: $scope.user.tags[i].data } }).success(function (response) {
if (response == "true") {
// $scope is always undefined here
$scope.user.tags[i].is_valid = false;
$scope.tags_valid = false;
} else if (response == "false") {
// $scope is always undefined here
$scope.user.tags[i].is_valid = true;
}
});
}
}, true);
Actually what is undefined is the user tag at [i].
Because of the function scope of the variable, the i will be equal to the length of the array before any response from server arrives.
You could wrap the server call in a function that would accept the index or the actual tag as an argument. Like checkTag(tag) in which you make the call.
Example code:
function checkTag(tag) {
$http.get("api/registration/TagExists", { params: { Tag_Id: tag.data } }).success(function (response) {
if (response == "true") {
tag.is_valid = false;
$scope.tags_valid = false;
} else if (response == "false") {
tag.is_valid = true;
}
});
}
im using ag-Grid, but there is a issue when it filters my data, when i filter my data in the price column, it only works with numbers dot and not with commas.
Link: https://plnkr.co/edit/LDdrRbANSalvb4Iwh5mp?p=preview
Practical Example:
In the Price column select box equal and above insert "1.5" and than try inserting "1,5"
This is because this filter is a native one.
If you want to handle custom behaviour, define your own filter.
Documentation : https://www.ag-grid.com/angular-grid-filtering/index.php
A quick and dirty solution would be to monkey patch the NumberFilter like this :
NumberFilter.prototype.doesFilterPass = function (node) {
if (this.filterNumber === null) {
return true;
}
var value = this.valueGetter(node);
if (!value && value !== 0) {
return false;
}
var valueAsNumber;
if (typeof value === 'number') {
valueAsNumber = value;
}
else {
valueAsNumber = parseFloat(value.replace(',','.'));
}
switch (this.filterType) {
case EQUALS:
return valueAsNumber === this.filterNumber;
case LESS_THAN:
return valueAsNumber < this.filterNumber;
case GREATER_THAN:
return valueAsNumber > this.filterNumber;
default:
// should never happen
console.warn('invalid filter type ' + this.filterType);
return false;
}
};
Then changed line is here :
valueAsNumber = parseFloat(value.replace(',','.'));
So i found the problem, first i had to convert the value has a string than i needed to replace the dot by the comma, the problem with the answer above was first because of the data type and than the order of the properties of the replace function, but the problem now is that is not filtering correctly, if i search using equal option if gives me 2 values, instead a fixed one, code looks something like this:
Code:
NumberFilter.prototype.doesFilterPass = function (node) {
if (this.filterNumber === null) {
return true;
}
var value = this.valueGetter(node);
if (!value && value !== 0) {
return false;
}
var valueAsNumber;
if (typeof value === 'number') {
value = value.toString()
valueAsNumber = parseFloat(value.replace('.',','));
}
else {
valueAsNumber = parseFloat(value.replace('.',','));
}
switch (this.filterType) {
case EQUALS:
return valueAsNumber === this.filterNumber;
case LESS_THAN:
return valueAsNumber < this.filterNumber;
case GREATER_THAN:
return valueAsNumber > this.filterNumber;
default:
// should never happen
console.warn('invalid filter type ' + this.filterType);
return false;
}
};
Possible Solution:
NumberFilter.prototype.onFilterChanged = function () {
var filterText = utils_1.default.makeNull(this.eFilterTextField.value);
if (filterText && filterText.trim() === '') {
filterText = null;
}
var newFilter;
if (filterText !== null && filterText !== undefined) {
console.log(filterText);
// replace comma by dot
newFilter = parseFloat(filterText.replace(/,/g, '.'));
console.log(newFilter);
}
else {
newFilter = null;
}
if (this.filterNumber !== newFilter) {
this.filterNumber = newFilter;
this.filterChanged();
}
};
I was asked to change some code using lodash's _.every:
//for every item in collection, check if "someProp" is true,
//but only if "someProp2" isn't "-1". If "someProp" is true for
//every item in collection, return true.
$scope.areAllTrue = function() {
for(var i=0; i<$scope.collection.length; i++){
if($scope.collection[i].someProp2 === -1) {
continue;
}
if(!$scope.collection[i].someProp) {
return false;
}
}
return true;
};
So following the lodash example of:
_.every(users, 'active', false);
We get:
$scope.areAllTrue = function() {
return _.every($scope.collection, 'someProp', true)
};
This handles the "For every item in the collection, check if someProp is true, if all are true, return true." But can I do the "continue" check here somehow?
Edit: Can I use two predicates with "_.every" somehow? Like if someProp1 === true || someProp2 === -1 ?
_.every() can use a predicate function:
_.every(users, function(user) {
return user.someProp2 === -1 || user.someProp;
});
You can also skip lodash, and use Array.prototype.every:
users.every(function(user) {
return user.someProp2 === -1 || user.someProp;
});
I would like to extend some properties recursive (aka. deep copy).
much like jQuery does. I'm not including jquery only b/c of one thing.
jQuery.extend( true, target, object1 )
is there any elegant way you know of that does it with simple javascript or angularjs?
update
please take a look and try to accomplish the same result
http://plnkr.co/edit/GHabYbyhsqtfBPtplksO?p=preview
i did look into .copy() but the "properties (for objects) are deleted"
Here is an extendDeep function based off of the angular.extend function. If you add this to your $scope, you would then be able to call
$scope.meta = $scope.extendDeep(ajaxResponse1.myMeta, ajaxResponse2.defaultMeta);
and get the answer you are looking for.
$scope.extendDeep = function extendDeep(dst) {
angular.forEach(arguments, function(obj) {
if (obj !== dst) {
angular.forEach(obj, function(value, key) {
if (dst[key] && dst[key].constructor && dst[key].constructor === Object) {
extendDeep(dst[key], value);
} else {
dst[key] = value;
}
});
}
});
return dst;
};
Note: This function has the side-effect of copying values from later arguments into the earlier arguments. For a simple fix to this side effect, you can change dst[key] = value to dst[key] = angular.copy(value).
All the answers here are valid for versions of Angular before 1.4
As of Angular 1.4, you can use angular.merge to do exactly that:
Unlike extend(), merge() recursively descends into object properties of source objects, performing a deep copy.
https://docs.angularjs.org/api/ng/function/angular.merge
function deepExtend(destination, source) {
for (var property in source) {
if (source[property] && source[property].constructor &&
source[property].constructor === Object) {
destination[property] = destination[property] || {};
arguments.callee(destination[property], source[property]);
} else {
destination[property] = source[property];
}
}
return destination;
}
Plunker
Src: https://gist.github.com/gregdangelo/2343158
Building on Ryan's code, you can shorten the object check and you should also NOT extend functions so you don't override object pointers.
var extendDeep = function extendDeep(dst) {
angular.forEach(arguments, function(obj) {
if (obj !== dst) {
angular.forEach(obj, function(value, key) {
if (dst[key] && angular.isObject(dst[key])) {
extendDeep(dst[key], value);
} else if(!angular.isFunction(dst[key])) {
dst[key] = value;
}
});
}
});
return dst;
};
The same solution as Ryan but with support for array merge
function extendDeep(dst) {
angular.forEach(arguments, function (obj) {
if (obj !== dst) {
angular.forEach(obj, function (value, key) {
if (dst[key] && dst[key].constructor && dst[key].constructor === Object) {
extendDeep(dst[key], value);
} else if (dst[key] && dst[key].constructor && dst[key].constructor === Array) {
dst[key].concat(value);
} else if(!angular.isFunction(dst[key])) {
dst[key] = value;
}
}
);
}
}
);
return dst;
}
Angular has a copy method:
angular.copy