InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe', cannot modify HTML - javascript

I am working to populate a dropdown on an application using Angular and ngrx. The app uses a dropdown component which is used across the entire application for dropdowns, so I cannot modify it.
The HTML from that component which is most important for my question is as follows:
<option *ngFor="let option of options" [value]="stringifyOption(option.value)" [selected]="option.value === (selectedValue | async)">
{{option.text}}
</option>
I am getting my dropdown options, which is an array of objects (dateOptions), from the store. Each object has a property value (week) which I am getting and setting as the options for the dropdown.
this.weekDropdownOptions = dateOptions.map(weekObj => weekObj.week);
Logging weekDropdownOptions in the console returns an array of the options like I was expecting, like this:
["04/01 - 04/07", "04/08 - 04/14"]
My HTML has the selector for the dropdown and sets [options]="weekDropdownOptions"
I can't seem to get past this error:
InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe'.
It is pointing towards the dropdown component, however I can't modify the HTML. What can I do in my code to make this work?

the async pipe expects an Observable and not an Object. it would be interesting to see how exactly selectedValue is populated and why it's used with the async pipe.
here is an example on the difference in stackblitz https://stackblitz.com/edit/angular-vv7pzs

The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted.
According to the error, selectedValue is an object so you can not use the async pipe.

Related

Vue-multiselect: How to convert object to array for use in options prop?

I am using vue-multiselect like so:
<multiselect
id="customer_last_name_input"
v-model="value"
:options="activeUserProfiles"
label="lastname"
placeholder="Select or search for an existing customer"
track-by="uid"
:close-on-select="true"
#select="onSelect"
#remove="onRemove"
:loading="isLoading"
:custom-label="customerSelectName"
aria-describedby="searchHelpBlock"
selectLabel=""
>
...that grabs the list of active customers from an Array and then makes them available in a nice select menu.
This works good. However, I need to add another option from another resource (called customerNone) to the options prop and but the data is returned as an Object like so:
{"uid":1,"lastname":"None Given","firstname":"User","email":null,"phone":null...blah}
The vue-multiselect docs state that the :option prop MUST be an Array.
Question: What is the best way for me to handle this in the vue-multiselect component? Here's my attempt to help explain what I am trying to do (not sure if this is the best way to handle it). Unfortunately, my attempt causes a console error (see below):
I am passing a prop down called noCustomer which, if is true, I need to use customerNone profile on :options:
<multiselect
:options="noCustomer ? customerNone : getActiveUserProfiles"
>
here's the error:
Invalid prop: type check failed for prop "options". Expected Array, got Object
Is there a way I can convert the customerNone object to an array of object? Thanks!
You could wrap the customerNone object in brackets at the time that you pass it to the <multiselect> like [customerNone].
This syntax creates a new array on the fly, having 1 element that is the object variable:
<multiselect
:options="noCustomer ? [customerNone] : getActiveUserProfiles"
>
Update for comments
In order to auto-select the generic option when it's available, use a watch on the noCustomer prop to set value whenever noCustomer === true:
watch: {
noCustomer(newValue, oldValue) {
if(newValue) { // Checking that `noCustomer === true`
this.value = this.customerNone;
}
}
}

Passing string list to javascript function Django

Im building my first Django app.
I want to call a javascript function that receives a list of strings.
In my current version Im sending a Django object (called provider) property like this and it´s working fine:
<i class="fi-download"></i>
But now I want to call a Provider model method that returns a list of strings, so then I can do something with this list in Js method
def get_provider_files_urls(self):
provider_files = self.provider_files.all()
file_list = []
for f in provider_files:
file_list.append(f.file.name)
return file_list
I tried this:
<i class="fi-download"></i>
and got this error:
Uncaught SyntaxError: missing ) after argument list
A quick and dirty way to generate a JS array from a list is to use the join filter
onclick="download_provider_files(['{{ provider.get_provider_files_urls|join:"', '" }}'])"
Probably cleaner to use the json_script filter though

ERROR TypeError: Cannot read property 'list' of undefined

Getting the error as mentioned when I am trying to get the response from API call and display the information in the response object in the template.
ERROR TypeError: Cannot read property 'list' of undefined.
In service.ts, I am making a server call. I am using OpenWeatherMap API.
getDetails(cityName, countryCd): Observable<any>{
return this.httpclient.get(`${this.url}${cityName},${countryCd}&APPID=${this.apiKey}`);
}
Object format returned by the API:
{"city":{"id":1851632,"name":"Shuzenji",
"coord":{"lon":138.933334,"lat":34.966671},
"country":"JP",
"cod":"200",
"message":0.0045,
"cnt":38,
"list":[{
"dt":1406106000,
"main":{
"temp":298.77,
"temp_min":298.77,
"temp_max":298.774,
"pressure":1005.93,
"sea_level":1018.18,
"grnd_level":1005.93,
"humidity":87,
"temp_kf":0.26},
"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"}],
"clouds":{"all":88},
"wind":{"speed":5.71,"deg":229.501},
"sys":{"pod":"d"},
"dt_txt":"2014-07-23 09:00:00"}
]}
In home.component.ts, I am subscribing to the service API call. I am getting the reposnse which is of type 'object'.
I have an array of objects called cities. I am loading the response object from the server as one of the property in each object of the array cities.
this.cities = this.cityService.getCities().slice();
this.cities.forEach(element => {
this.weatherService.getDetails(element.cityName, element.countryCd).subscribe(response => {
element['cityWeather'] = response;});
});
In home.component.html, I am iterating this cities array and the using the response data from the API. The data is displayed properly without any issues.
But in the console I am seeing an error for every iteration of cities array -
ERROR TypeError: Cannot read property 'list' of undefined.
<div class="col-md-4" *ngFor="let city of cities; let i = index">
<span>{{city.cityWeather.list[0].main.temp | kelvinToCelcius}} ℃</span>
<span>{{city.cityWeather.list[0].wind.speed | mtrPersecToKmPerhr}} km/h</span>
</div>
I am relatively new to Angular, need to know what is this error about and how this can be resolved.
Your issue is that in your home component you refer to
<span>{{city.cityWeather.list[0].main.temp | kelvinToCelcius}} ℃</span>
<span>{{city.cityWeather.list[0].wind.speed | mtrPersecToKmPerhr}} km/h</span>
These values may not be defined at all times, so if city.cityWeather is undefined, accessing the .list property would result in the error
Cannot read property 'list' of undefined.
You can fix this by using the Angular safe navigation operator (also known as the Elvis operator).
The Angular safe navigation operator (?.) is a fluent and convenient way to guard against null and undefined values in property paths
-- Angular docs
By changing . to ?., Angular will not throw an error if it can't find the property on the object.
Note that this only works in component templates, and not in TypeScript files.
You can either use The Angular
safe navigation operator (?.)
city.cityWeather?.list[0]?.main.temp
city.cityWeather?.list[0]?.wind.speed
or you can try using Angular async pipe
https://angular.io/api/common/AsyncPipe
Try to change your code like this:
<div class="col-md-4" *ngFor="let city of cities; let i = index">
<span>{{city?.cityWeather?.list[0]?.main?.temp | kelvinToCelcius}} ℃</span>
<span>{{city?.cityWeather?.list[0]?.wind?.speed | mtrPersecToKmPerhr}} km/h</span>
</div>
This may be due the fact that your getCities() request is completed and your getDetails() call is yet to return response which it will give at some point in time due to the asynchronous nature of code. So when the loop execute cityWeather is not available and you get the error. The ? will not throw error but instead it will show data when it will be available.

Angular ng-select : selectedItems.map is not a function

When I'm using ng-select in reactive form angular I get this error:
ERROR TypeError: selectedItems.map is not a function
I have 3 select the first two work very well but in this third one I get the error ! to map item i'm using the function (the ng-select is inside *ngFor) :
//for mappinig item :
mapLabelValueBS(objet) {
return objet.map(data => {
return {
id: data,
text: data.name
}
})
}
//this is the one that is causing the problem
<ng-select
[allowClear]="true"
[items]="mapLabelValueBS(filieres)"
placeholder="Filière non sélectionné"
(selected)="selecteFiliere($event)"
formControlName="filiere">
</ng-select>
the result in my page (when I click on the field it doubles itself) :
Without the code is difficult to know, but today I had the same error. The reason was that I determined a default value in the FormControl that had no relation with the array that ng-select demands. When the FormGroup loaded, and this mistaken default was loaded into the ng-select, the error was selectedItems.map is not a function
This error came while I was passing [items]="value" where the value was not an array, so please check if you are not passing non array element to items binding.
You are trying to bind the items of object type. [items] attribute accepts an array. You can trying adding a pipe keyvalue
<ng-select
[allowClear]="true"
[items]="jsonData | keyvalue"
placeholder="Filière non sélectionné"
(selected)="selecteFiliere($event)"
formControlName="filiere">
</ng-select>
few days ago i came across this error if you are binding a list that is filled from backend server be sure to fill the list using concat method like this
this.userService.getLookup().subscribe((res: any) => {
this.apps = this.apps.concat(res.data);
});
I had same problem, because the list of items was undefined sometime in the middle of page preparing, so I added a silly condition to show those select only when the list of items is ready:
<ng-select
*ngIf="selectedItems.map"
[allowClear]="true"
[items]="jsonData | keyvalue"
placeholder="Filière non sélectionné"
(selected)="selecteFiliere($event)"
formControlName="filiere">
</ng-select>

How to set type dynamically in typescript using 'es6' style?

Looking for a smart way to structure my code (ES6 style). Without if statement.
My angular component app-slider has an attribute what enables the component to get data from the parent (using #Input); The value that comes into the app-slider component is wither 'city' or 'event'.
The two child component
<app-slider [context]="'city'"></app-slider>
<app-slider [context]="'event'"></app-slider>
The purpose of the two are the same - they display some information - either about cities or about events.
Based on the value 'city' or 'event' I would like to call my mongo db to fetch the corresponding data.
I can easily call my database layer in my constructer and call either getCities() or getEvents(). I can use an if statement.
But would it be possible to it without an if statement - a more clean way?
Thanks again
Can you create dictionary :
dict = {
event: Event,
city: City}
then
var data = dict[stringType];
// Event or City

Categories

Resources