Invalid Argument: Cannot use an empty value with the AsyncPipe at invalidArgumentError

I'm facing an issue with extracting a string value from the Observable using the pipe and map operators. Despite my efforts, I always end up with an empty string as the result. I'm hoping that someone can assist me in understanding the cause of this problem.

Here is the http service method that retrieves a file from the backend:

getFiles(url: string, idProject: number, docProject: string): Observable<any> { 
return this.http.get(`${this.hostUrl}${url}/${idProject}/${docProject}`); 
  }

My call to the getFiles(...) method looks like this:

  showFile = false;
  fileUploads: Observable<string[]>;
.
.
.
showFiles(enable: boolean) {
    this.showFile = enable;

    if (enable) {
this.uploadService.getFiles('/projets', this.service.getProjet().idProjet,
  'documentProjets/pv/'//+ td.nomTypeDoc +'/getallfiles')
            .pipe( 
                  map( response => {
                  return response.slice(
                         response.indexOf("files"), 
                         response.lastIndexOf("?"))
                         })).subscribe(
                           (data) => {
                            this.fileUploads=data
                            console.log(data)},
                           (error) => console.log(error));
}
}

The original result before applying the map function is:

http://localhost:8080/api/v1/pv/files/file1.jpg?projetId=563, http://localhost:8080/api/v1/pv/files/file2.jpg?projetId=563 

However, after using the map function, the result is an empty array.

Below is the corresponding HTML:

<button class="button btn-info" *ngIf='showFile' (click)='showFiles(false)'>Hide Files</button>

<button class="button btn-info" *ngIf='!showFile' (click)='showFiles(true)'>Show Files</button> 


<div [hidden]="!showFile">
  <div class="panel panel-primary">
    <div class="panel-heading">Liste des fichiers</div>

    <div *ngFor="let file of fileUploads | async">  
      <div class="panel-body">
        <app-details-upload [fileUpload]='file'></app-details-upload>
      </div>
    </div>
  </div>
</div>

I'm puzzled about why I am getting an empty value and this is the error message from my console:

ListUploadComponent.html:3 ERROR Error: InvalidPipeArgument: '' for pipe 'AsyncPipe' at invalidPipeArgumentError (common.js:3981) at AsyncPipe.push../node_modules/@angular/common/fesm5/common.js.AsyncPipe._selectStrategy (common.js:4590) at AsyncPipe.push../node_modules/@angular/common/fesm5/common.js.AsyncPipe._subscribe (common.js:4580) at AsyncPipe.push../node_modules/@angular/common/fesm5/common.js.AsyncPipe.transform (common.js:4562) at Object.eval [as updateDirectives] (ListUploadComponent.html:10) at Object.debugUpdateDirectives [as updateDirectives] (core.js:11054) at checkAndUpdateView (core.js:10451) at callViewAction (core.js:10692) at execComponentViewsAction (core.js:10634) at checkAndUpdateView (core.js:10457)

Any help on this matter would be greatly appreciated. Thank you.

Answer №1

When using the async pipe, it automatically subscribes to an Observable in the template and handles the unsubscription on component destruction. It's recommended to follow the convention of adding a $ sign at the end of observable stream variables.

For example:

<div *ngFor="let v of values$ | async">
  {{v}}
</div>

is the same as:

<div *ngFor="let v of values">
  {{v}}
</div>

In your TypeScript file, you can achieve the same result by subscribing manually:

this.values$.subscribe(values => this.values = values)


In your code snippet, you have the option to either remove the async pipe from the template or remove the subscription and assign the stream directly.

this.fileUploads$ = this.uploadService.getFiles('/projets', this.service.getProjet().idProjet,
  'documentProjets/pv/'//+ td.nomTypeDoc +'/getallfiles')
            .pipe( map( response => {
                  return response.slice(
                         response.indexOf("files"), 
                         response.lastIndexOf("?"))
                         }))

If you require logging for debugging purposes, consider using the tap RxJS pipeable operator.


Update - steps after debugging

The tap operator is used for side effects like logging and does not modify the stream. It helps you understand the data being passed to the next operator in the pipe, which in this case is an array of strings. Adjust your code accordingly:

this.fileUploads$ = this.yourService.pipe(
    // tap(console.log),
    map((responseUrls: string[]) => {
        return responseUrls.map((url: string) => {
           // perform operations on the string here
           // e.g. using string methods or regex
           return url.slice(
               url.indexOf(‘files’),
               url.indexOf(‘?’)
           )
        })
    })
    // }),
    // tap(console.log)
)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to trigger this Angular function upon page load?

I have an async function called getDataStandard() that I want to execute without the need for a click event. Can someone please guide me on how to achieve this as I am new to Ionic? async getDataStandard() { let loading = await this.loadingCtrl.create ...

Monitor the change in values upon pressing the submit button on Angular

I am currently working with an edit form that contains data in the input fields. <ng-form #infoForm="ngForm" novalidate> <div> <label for="firstName">First Name :</label> <input type=" ...

Refreshing Angular2 View After Form Submission

Currently, I am in the process of developing a basic CRUD application with Angular2. The application comprises of a table that displays existing records and a form for adding new records. I am seeking guidance on how to update the table to show the new rec ...

Cannot trigger event ascn.onchange does not exist as a function

Need to trigger the onChange function and pass parameters within it. Here's what I have tried: setTimeout(function() { document.getElementById(input.key)?.onchange({}) }, 200); Encountering the following error message: cn.onchange is not a function ...

Deactivating PrimeNG checkbox

I am currently facing an issue with disabling a PrimeNG checkbox under certain conditions by setting the disabled property to true. However, whenever I click on the disabled checkbox, it refreshes the page and redirects me to the rootpage /#. To troublesh ...

Implementing ngFor to Iterate Through a JSON Object in Angular 6

Iterate through the object list retrieved from a JSON object Here is the JSON object that I have fetched: { "0": { "0": null, "1": "Consolidated Statements of Changes in Stockholders\u2019 Deficit", "2": null, "3": "", "4": "" ...

What are some ways to customize formControlNames in Angular reactive forms?

Is there a way to customize the formControlName in Angular forms? I need to be able to toggle check-boxes on and off based on certain values within a nested object array. Here is an example of what the HTML code might look like: <span class="col-md-2" ...

Is it possible for me to define TypeScript interfaces to be used in vanilla JavaScript projects within VSCode?

While using the MS VisualCode editor, I am attempting to implement type checking in my Javascript code. I want to maintain the flexibility of Javascript while also benefiting from type checking interfaces and data structures. Based on the vscode documenta ...

Enhance your TypeScript code using decorators with inheritance

Exploring the realm of Typescript decorators has led me to discover their intriguing behavior when combined with class inheritance. Consider the following scenario: class A { @f() propA; } class B extends A { @f() propB; } class C exten ...

Troubleshooting issue with Vue Class Component and Vuex-class causing ESLint error

I am interested in utilizing vuex-class to bind helpers for vuex and vue-class-component However, an error message is displayed: Error: Parsing error - Using the export keyword between a decorator and a class is not allowed. Please use `export @dec class ...

Utilizing material-ui with Autocomplete featuring various value and option types

In my code, I am looking to store only an option's ID in a value For autocomplete functionality, the value's type and the option's type need to be the same My solution was to change the value in onChange, which worked successfully However ...

Error in JavaScript: A surprise anonymous System.register call occurred

Within Visual Studio 2015, there exists a TypeScript project featuring two distinct TypeScript files: foo.ts export class Foo { bar(): string { return "hello"; } } app.ts /// <reference path="foo.ts"/> import {Foo} from './f ...

Ways to mock a static method within an abstract class in TypeScript

Having a difficult time testing the function Client.read.pk(string).sk(string). This class was created to simplify working with dynamoDB's sdk, but I'm struggling to properly unit test this method. Any help or guidance would be greatly appreciate ...

Retrieving routing information from directives within angular2

const APP_ROUTES: RouterConfig = [ { path: 'app/home', component: HomeComponent, data: { name: 'Home' } } ] Assuming the route configuration is set as displayed above, how can one ...

Testing the derived class resulted in failure with the error message: "Unable to resolve all parameters for : (?, ?) in Angular 5."

Encountering an issue when trying to run Karma on a structure consisting of an abstract class, a derived class, and a test. The error message that is being thrown is: Failed: Can't resolve all parameters for ActivationsComponent: (?, ?). The abstrac ...

Tips for integrating Typescript Definition files with Visual Studio 2017

I have a challenge with my ASP.NET Core 2.0 application where I am attempting to incorporate TypeScript and jQuery. While TypeScript integration has been successful, I am facing issues with jQuery as it does not provide me with intellisense. Despite trying ...

Utilizing a nested interface in Typescript allows for creating more complex and

My current interface is structured like this: export interface Foo { data?: Foo; bar?: boolean; } Depending on the scenario, data is used as foo.data.bar or foo.bar. However, when implementing the above interface, I encounter the error message: Prope ...

Types of navigation items based on conditions

I want to create an interface where a navigationItem can have optional childs for a dropdown menu. If the childs property is provided, I want to require the icon property in the navigationItem object. If no childs are given, the icon property should not be ...

Sharing the input value with a service in Angular 4

I am a beginner when it comes to Angular 4. I currently have a variable named "md_id" which is connected to the view in the following way. HTML: <tr *ngFor="let item of driverData"> <td class="align-ri ...

What is the best way to conduct tests on this React component using Jest?

I'm currently working on increasing the test coverage for a wrapper component in my codebase using jest. Although I haven't been able to identify any specific usage of this component, it's important to ensure that it is covered by tests. M ...