0
votes

I have a problem. I found lots of information that async pipe expects Observables. So, I thought that I return observable from my service on socket.on event, but seems like I am wrong. How should I correctly implement that?

service:

public getUsers(): Observable<any> {
    return new Observable<any>(observer => {
        this.socket.on('my_users', (data) => observer.next(data));
    });
}

component:

users: Observable<any[]>;

this.http.getUsers().subscribe((user: any) => {
    this.users = user.data;
});

template:

<button class="send_to_username" 
        value="{{user}}" 
        *ngFor='let user of users;  let i = index' 
        [ngClass]="{'active':isClicked[i]}"
        (click)="isClicked[i] = (isClicked[i]? false :true); getReceiver(user)"
>{{user | async}}</button>

server:

@socketio.on('username', namespace='/private')
def receive_username(username):
users[username] = request.sid
print('Username added!')
print(users)
emit('my_users',
     {'data': list(users.keys())})

ERROR Error: "InvalidPipeArgument: '111111' for pipe 'AsyncPipe'"

1
Why are you using the async pipe there? The user value there is not an observable. There error is telling you that the value is '111111'. - Daniel W Strimpel
@DanielWStrimpel I need this list of buttons to dynamically change on different similar pages - Дамир Саматов

1 Answers

0
votes

You're declaring users as an Observable. But it's getting initialised as something else, i.e. your data.

// This part is a subscription to an observable:
this.http.getUsers().subscribe((user: any) => {
    // This part is just a regular assignment:
    this.users = user.data;
});

So this line is wrong: users: Observable<any[]>;

Instead it should be something like: users: Array<any> = []

Your error is actually because of something else though. You're using the async pipe incorrectly.

<button
    class="send_to_username"
    value="{{user}}"
    *ngFor='let user of users; let i = index'
    [ngClass]="{'active':isClicked[i]}"
    (click)="isClicked[i] = (isClicked[i]? false :true); getReceiver(user)"> 
    {{user | async}}
</button>

Should be:

<button
    class="send_to_username"
    value="{{user}}"
    *ngFor='let user of users; let i = index'
    [ngClass]="{'active':isClicked[i]}"
    (click)="isClicked[i] = (isClicked[i]? false :true); getReceiver(user)"> 
    {{user}}
</button>

However, if you wanted to pipe the output of your Observable then you can remove all of this:

users: Observable<any[]>;

this.http.getUsers().subscribe((user: any) => {
    this.users = user.data;
});

And instead just write:

<button
    class="send_to_username"
    value="{{user}}"
    *ngFor='let user of (http.getUsers() | async); let i = index'
    [ngClass]="{'active':isClicked[i]}"
    (click)="isClicked[i] = (isClicked[i]? false :true); getReceiver(user)"> 
    {{user}}
</button>