Cannot read property 'toLowerCase' of undefined Angular 5 - javascript

I am trying to filter a column of a ngx-table I follow the the example but it keeps giving that error "Cannot read property 'toLowerCase' of undefined"
here's the template part
<ngx-datatable-column name="Nom" class="name">
<ng-template ngx-datatable-cell-template let-value="value">
{{value}}
</ng-template>
</ngx-datatable-column>
and the function attached to it
updateFilter(event) {
const val = event.target.value.toLowerCase();
// filter the data
const temp = this.temp.filter(function(d) {
return d.name.toLowerCase().indexOf(val) !== -1 || !val;
});
// update the rows
this.rows = temp;
// Whenever the filter changes, always go back to the first page
this.table.offset = 0;}
Any idea of how to solve this?

It would appear that the the items being filtered through do not all contain a value 'name' within them. Try console.log(d) before your return within that function to verify you are receiving the data you expect.

It appears that your name property must be undefined in some cases. This could be that it is not the correct property name (is it lastName instead of name?) or that for some objects in the temp array that the value is undefined. In either case, you can check for a null first before returning the value.
if (d.name) {
return d.name.toLowerCase().indexOf(val) !== -1 || !val;
} else {
return null;
}

Related

Rejection when changing array property in React

I receive an object from the api and I need to change the maximum quantity, I created a copy with let but the rejection still occurs as if I were using a const in this copy.
produtosComplementares = [
{
"codigo":null,
"codigoProduto":2,
"descricao":'ADICIONAL PDV',
"imagem":null,
"nome":null,
"quantidadeMaxima":1
},
{
"codigo":null,
"codigoProduto":941,
"descricao":'ADICIONAL Retaguarda',
"imagem":null,
"nome":null,
"quantidadeMaxima":0
}
];
let arrayTemporario: any = [...produtosComplementares];
arrayTemporario.map((item: any) => {
if(item.codigoProduto == 2{
item.quantidadeMaxima = 3
}
});
the following rejection occurs:
TypeError: Cannot assign to read only property 'quantidadeMaxima' of object '#'
when you are mapping over the object you are getting each key value of the object
so if the item key is codigoProduto and it equals 2 you can not item can not also be the key quantidadeMaxima.
I think it would be very easy for you to debug this or just print item inside the map function.

Skipping undefined elements from an API call

I am gathering data from an API to show the Pokemon typing. Some Pokemon have one type, while others have two.
The variables to gather the typing data are as such.
function createPokemonCard(pokemon) {
const type = pokemon.types[0].type.name;
const second_type = pokemon.types[1].type.name;
...}
And then I call them via InnerHTML in the same function with the following code.
<small class="type"><span>${type}/${second_type}</span></small>
Predictably, when it hits undefined for a Pokemon, it breaks and doesn't display the card. However I am not sure how to get it to not print the second type when it's undefined.
I thought about doing an if statement, but what should I call if there is an undefined variable?
function undefined {
if(second_type === 'undefined') {
???
}}
Or would a for loop work better? I am not sure how to get it to bypass the undefined and print nothing.
const second_type = pokemon.types[1] ? pokemon.types[1].type.name: undefined;
`<small class="type"><span>${type}${second_type!=undefined ? `/${second_type}`: ''}</span></small>`
The ? : syntax is a ternary operator (mdn)
It's a less verbose way of writing out the following:
if (second_type!=undefined) { // check if second_type is not undefined
return `/${second_type}` // if it's not return / and the second type
} else { //otherwise
return '' // return an empty string
}
If you do not want to display the trailing / when second_type is not defined one way to go could be
const type = pokemon.types.map(({ type }) => type.name).join("/")
and then
<small class="type"><span>${type}</span></small>

Cannot read property 'indexOf' of undefined

Im trying to search if a value exits in an array. Im using ui-select to capture the values, and i create function to verify if the value exists and all works great but the console show me many times Cannot read property 'indexOf' of undefined.
here the select codes used to capture the data
<ui-select multiple ng-model="entrevistainicialModel.personalidad"
ng-disabled="false"
search-enabled="true"
append-to-body="true"
class="form-control ">
<ui-select-match placeholder="Comportamientos">
{{$item.comportamiento}}
</ui-select-match>
<ui-select-choices repeat="multipleItem.idcomportamiento as multipleItem in datosJson[0].comportamientos | filter: $select.search">
{{multipleItem.comportamiento}}
</ui-select-choices>
</ui-select>
here is the checkbox code with the function
<td class="text-center"><input type="checkbox" ng-checked="check(entrevistainicialModel.personalidad, 1)" value="1"></td>
and here it's the function
$scope.check = function (data, n) {
if (data.indexOf(n) !== -1) {
return true;
} else {
return false;
}
}
all works great! only the console send me many times the error of indexOf
If you can not read indexOf of data it is because data is undefined.
I wanted to say that data have no value in it so it can not have methods like indexOf. You can check like this:
console.log (typeof data);
Here, you try to read the type of value in data. If the result is undefined it's mean that data is empty.
So, you have to check if data is not empty (undefined). You can check it like that:
$scope.check = function (data, n) {
if (!data) {return;} // If data is undefined return.
if (data.indexOf(n) !== -1) {
return true;
} else {
return false;
}
}
It's because data contains undefined, its because of what you are passing is undefined or from somewhere else you are passing nothing to this method. As per your code, I can say entrevistainicialModel.personalidad should be initialized with an array or string or something like tha, which have the indexOf method, then you will not get this error Cannot read property 'indexOf' of undefined
Otherwise you should handle the scenario like (data || []).indexOf(...)

angularjs function failing because of extra $$hashKey

I have the below HTML:
<li ng-click="toggleBeep(beep)" ng-class-odd="'gradient-two'"
ng-class-even="'gradient-three'" ng-repeat="beep in beeps">
<span>{{beep.name}}</span>
<label class="bold" ng-show="isSelected(beep)">selected</label>
</li>
JavaScript (AngularJS):
$scope.beeps = $sounds.getAll();
// get stored beep from localStorage
var notification_beep =
angular.fromJson(localStorage.getItem('notification_beep'));
console.log($scope.beeps[0]);
console.log(notification_beep);
// handle change sound on click event
$scope.toggleBeep = function (beep) {
$cbSounds.play(beep.file);
$scope.selected = beep;
localStorage.setItem('notification_beep', angular.toJson(beep));
};
$scope.isSelected = function (beep) {
return $scope.selected === beep;
};
Now, when I click on any li I get the selected label is shown because of the $scope.isSelected function. However, when I try to add this line $scope.selected = notification_beep which is the beep object stored in the localStorage the label is not shown and I get the below return values.
The only difference I could spot is that $$hashkey is present on $scope.beeps[0] while it's not on notification_beep. Could this be the cause? Thanks.
The following comparison:
$scope.selected === beep
Will only return true if the two variables reference the same object.
The following line will create a new object:
var notification_beep = angular.fromJson(localStorage.getItem('notification_beep'));
So it will not reference the same object as $scope.selected.
To clarify, this will return false: { name: 'Beep 1' } === { name: 'Beep 1' }
The simplest solution is to instead compare against a unique primtive of the objects.
For example:
return $scope.selected.name === beep.name;
The $$hashkey property is inserted into the object by ng-repeat and is used to track which object corresponds to which DOM template. The reason it doesn't exist in notification_beep is because angular.toJson removes the property from the object.

AngularJs why is object undefined on ng-disabled function?

VIEW:
I have a rows repeating , with a save button on each row to save each object individually. I want this button to be disabled if no changes have been made.
<tr ng-repeat="option in options | filter:search">
<a ng-click="save(option)" ng-disabled="isUnchanged(option)">Save</a>
</tr>
CONTOLLER:
So I pass the option object to the function, I get its index position in the array. Then compare this 'option' object to its original self in apiKeyOptions[index] which is injected as a service.
angular.module('PartOfApp')
.controller('PartOfAppCtrl', function( $scope, ... apiKeyOptions) {
$scope.options = apiKeyOptions;
$scope.isUnchanged = function(option) {
var index = $scope.options.indexOf(option);
//compare object to the original
if(option.value == apiKeyOptions[index].value && apiKeyOptions[index].setting == option.setting){
//then no changes have been made to this
return true;
}else{
return false;
}
For some reason I get a console of 100's of errors when any data is changed, saying that the apiKeyOptions[index].value and apiKeyOptions[index].setting are undefind.
The app works perfectly as it should returning true if they are the same but still throws a
TypeError: Cannot read property 'value' of undefined
on apiKeyOptions[index]
if I console.log(apiKeyOptions[index].value) I get no undefined values and all log correctly.
Im guessing Im breaking some angular rules, if anyone could help that would be great.
apiKeyOptions overview:
apiKeyOptions is an array of up to 50 objects
each object is in the form
{
defaultValue: boolean,
description: null,
name: String,
setting: "Default" or Boolean,
value: Boolean
}
Added after comment below:
If I add-
console.log(index);
console.log(apiKeyOptions[index]);
to the function $scope.isUnchanged, I get the expected results
example :
13
Object {name: "LOREM IPSUM", description: null, defaultValue: false, setting: "default", value: falseā€¦}
So index is not always -1. The reason I pass the object to the function and not $index is because of the filter | search so the index will change depending on the search.
FIXED
As shown in the answer below . I was getting a index = -1 error but its was buried in 100's of CORRECT log outputs.
Oddly this did not stop the app from working and I will need to have a deeper look into how ng-disabled is bound to a value. To fix I simply replaced the indexOf with
for (var i = 0; i< $scope.options.length; i++ ){
if($scope.options[i].name == option.name){
var index = i;
}
}
The problem seems to be with the parameter passed to $scope.isUnchanged = function(option) {
Since ng-repeat creates a new scope for each loop, i suspect that the 'option' available to each loop would be a new object and will not have a reference to 'options' array.
<tr ng-repeat="option in options | filter:search">
Therefore your isUnchanged function will receive parameter as a new object and hence below code always returns -1. Because indexOf matches the given argument in the array and since the argument 'option' is an object and doesn't refer(reference comparison) the same element of array hence no match will found. i.e var a = {id:1};var b = [a]; b.indexOf({id:1}) === -1; b.indexOf(a) === 0;
var index = $scope.options.indexOf(option);//always be -1 in your case
// therefore apiKeyOptions[index] will always be undefined
As a workaround you should pass $index to isUnchanged from the view.

Categories