I am stuck with an AngularJS filter issue and would appreciate an advise. In several different views I have numbers, like 1000000000, which are hard to read. Task is to separate each three digits' block by commas. To do that I have written a filter:
angular.module('AppCore')
.filter('numberCommaSeparator', function () {
return function (x) {
x = x.toString();
var pattern = /(-?\d+)(\d{3})/;
while (pattern.test(x))
x = x.replace(pattern, "$1,$2");
return x;
}
});
Added the filter in the view:
<span ng-if="project.value != 0">{{project.currency.name}} {{project.value|numberCommaSeparator}}</span>
<span ng-if="project.value == 0">N/A</span>
In two places out of three it works flawlessly, however, in the third case I do constantly receive a mistake:
Error: [$interpolate:interr] Can't interpolate: {{project.currency.name}} {{project.value|numberCommaSeparator}}
TypeError: Cannot read property 'toString' of undefined
What am I missing?
The error says that in some case your project.value is undefined
If that value is undefined, the first ng-if condition project.value != 0 is satisfied, not the second, you should check also for undefined to avoid that error.
Related
I am getting a TypeError on the following statement:
let uploadSignal = true;
mandatoryFields.forEach((element) => {
let field = this.state[element];
if(field.value === ""){
field.error = "Required!";
uploadSignal = false;
}
});
TypeError: Cannot read property 'value' of undefined
This means that you are trying to refer to a property called value on an undefined object. The only place you do that is here:
if(field.value === ""){
Which means field is undefined. field is being set here:
let field = this.state[element];
Which means this.state[element] is undefined.
i am asking why value is undefined and how to solve this error so that i can run my program
For the former, we can't know. You'll need to debug and discover what your runtime values are and why you expect this value to be defined. All we can say with certainty is that it's not.
For the latter, you can conditionally check if the value is "truthy" before trying to use it:
if(field && field.value === ""){
In the event that field is undefined then the left side of the && operation will be "falsy", which will cause the entire condition to be false without needing to evaluate the right ride of the && operation. With the condition being false, the if block isn't executed and the code continues.
I got this expression in my index.html:
{{place.file.name()}}
it contains a String like tfss-24af16c3-df1f-4c35-a1e1-281bd3af7c7a-Flightreservation.pdf.
I want to cut the first 42 characters by a filter:
{{place.file.name() | sliceFileName}}
The filter is this:
.filter('sliceFileName', function() {
return function(input) {
return input.slice(42);
}
})
And it works. However, the console prints:
[Error] Error: undefined is not an object (evaluating 'input.slice')
I read somewhere that input is either trueor false (don't know if it is correct). But it works as if input is the string.
Why does it still output an error?
Error means that sometimes your input is not a string. It could be, for example, before your place object has been initialized.
For your purpose you just can use built-in limitTo filter, because there already is some checks. It has second argument where you can set offset:
$scope.Infinity = Number.POSITIVE_INFINITY // you need to provide that into scope, because you need to set upper bound of limit
{{ string | limitTo:Infinity:42 }}
See plunker with full demo: http://plnkr.co/edit/o1fIh84OhptZrsYZ0vIV?p=preview
Because the filter get's evaluated before the content is loaded. You can check if the input has any content:
.filter('sliceFileName', function() {
return function(input) {
if(input) return input.slice(42);
}
})
And you won't get the console error anymore.
The code in this Plunker works as it should (just the first 3 links do something). But as the list started to grow I realized I needed a for loop. So within the switch function I transformed this:
if(obj == "SP") {
$scope.discipline ='Link2'
return $scope.files = spFiles;
}
else if(obj == "LSM"){
$scope.discipline = "Link3"
return $scope.files = lsmFiles;
}
else if(obj == "AR"){
$scope.discipline = "Link1"
return $scope.files = arFiles;
}
Into this:
for(i=0;i<disciplines.length;i++){
if(obj == disciplines[i].initial){
return $scope.files = disciplines[i].array;
}
}
The disciplines array is located at the top of the script.js file.
Problem is, now suddenly I am getting a dupes error when I click on one of the links. I haven't a clue what is duplicating. I read the documentation for this error and added the track by $index to the ng-repeat located on the bottom of index.html. Take a look at this Plunker to see what it does now. Certainly there is a simple explanation for this. I've never encountered this though.
The only other answer I could find on here that seems to pertain to my question is this one, but, the object that is being used by the ng-repeat isn't a JSON object I'm pretty sure:
spFiles.push({
floor:floors[c].name, initial:floors[c].initial, status:spFloorStatus[i]
});
Plus, it was working before I created the for loop causing the trouble.
I apologize if anything is unclear. Please, if you need me to clarify anything just let me know, I tried to be as thorough and as least confusing as possible.
That's because disciplines[i].array return just string, not your variable, named arFiles.
You can initialize these variables as:
var tempFiles={};
and then add:
tempFiles.arFiles={
floor:floors[c].name, initial:floors[c].initial, status:arFloorStatus[i]
};
and get :
return $scope.files = tempFiles[disciplines[i].array];
I am getting wrong behaviour with my ng-show directives.
<span class="spanLabel" ng-show="!minimumCharactersMet()" >You need at least {{ howManyMoreCharactersNeeded() }} characters more</span>
<span class="spanLabel" ng-show="isNumberOfCharactersWithinRange()" >Remaining characters: {{ howManyCharactersRemaining() }}</span>
<span class="spanLabel warning" ng-show="anyCharactersOver()" >{{howManyCharactersOver()}} characters too many</span>
When I try to input a text span is counting from below to warn user of 2 characters minimum, countdown works and after stays there and does not hide. Also second one does not show.
Here is my plunker link with all the functions and html.
Any ideas why I cant get it working?
Thanks
It seems as though your boolean is wrong. The minimumCharactersMet() boolean should call for a function on the scope. Like this:
$scope.minimumCharactersMet = function() {
return ($scope.howManyMoreCharactersNeeded() === 0);
};
Notice the braces after the howManyMoreCharactersNeeded call. Otherwise it would be as if you were asking for a variable not a function.
working plnkr
In addition to what #Reins said, the two other statements have these errors:
You're missing the same function-calling brackets on anyCharactersOver
The return statement in the howMany functions has a bracket error. It should be
return ( characters < 0 ? Math.abs(characters) : 0);
Also, the return value of isNumberOfCharactersWithinRange should be:
$scope.minimumCharactersMet() && !$scope.anyCharactersOver();
Plunker
PS: I'd use ng-hide instead of ng-show(!)
I have an Autocomplete working with geonames.org cities in the source: option and want to manipulate some of the arrays in the results. I have a "hard coded" test version running, but am having trouble manipulating the array variables to turn it into something useful.
A short statement of the problem is I can't get the alert statements to output readable strings. I get [object, Object] types of output. I need readable strings in the arrays for other code (not shown) to work. But other problems are: the Firebug Console output does not occur, and the Console gives me the following error statement - Error: Permission denied to access property 'item.autocomplete' - from line 2 of jQuery. This does not happen with the hard coded test. This is my first time using .grep and I'm not comfortable with .map, so I'm pretty sure the problems are array manipulations in those 3 sections.
Here's some relevant code. All the variables are declared, but I don't show all the declarations below.
citiesWithBoroughs = //a global array variable, populated in a prior select: option
source: function (request, response){
$.ajax({
success: function ( data ){
var geonamesResponse=$.map(data.geonames, function (item){
return {
label: item.name //and others
}
}
alert(citiesWithBoroughs + "," + citiesWithBoroughs.length + "|cWB2" ); //displays correct info
var noBoroughs=$.grep( geonamesResponse, function ( item, i ) {
for (var i=0; i < citiesWithBoroughs.length; i++ )
if( item.label === citiesWithBoroughs[i] ){ //compare geonamesResponse to each citiesWithBoroughs
console.log(citiesWithBoroughs[i]); //nothing in Console
return false; //drop any matches out of the geonamesResponse array
}
noBoroughs = $.map( data.geonames, function (item){ return item.label; });
console.log(noBoroughs); //nothing appears in Console
return true;
});
alert(noBoroughs.length + "," + citiesWithBoroughs.length + "," + geonamesResponse.length + "|3lengths" ); //correct info
alert(noBoroughs + "|nB" ); //in test, shows correct number of [object,Object] but no data
if( noBoroughs.length != geonamesResponse.length ){
var dropdownsCityWithBoroughs = $.grep( geonamesResponse, function ( item, i ) {
for (var i=0; i<citiesWithBoroughs.length; i++ )
if(item.label === citiesWithBoroughs[i]){return false;}
return true;
}, true )//true inverts grep to return the has-Boroughs city in the dropdown
alert(dropdownsCityWithBoroughs + "|dCWB"); //contains object, Object, but shows no data
}
}
}
}
I'm a novice so please give specific comments and code. I don't follow general instructions well.
The short statement of my problem was I could not read the output of my alerts, which contain arrays. Turns out JSON.stringify() fixes that. Other problems, like the Console.log statements not showing continue, but I can deal with that mysterious problem when the alerts work.