David
David

Reputation: 3604

Pass parameter to MdDialog in Angular Material 2

I'm using Angular Material 2 and I want to open a dialog window with MdDialog which shows some information about a user stored in firebase.

@Injectable()
export class TweetService {

  dialogRef: MdDialogRef<TweetDialogComponent>;

  constructor(public dialog: MdDialog) {
  }

  sendTweet(viewContainerRef: ViewContainerRef) {
    let config = new MdDialogConfig();
    config.viewContainerRef = viewContainerRef;

    this.dialogRef = this.dialog.open(TweetDialogComponent, config);

    this.dialogRef.afterClosed().subscribe(result => {
      this.dialogRef = null;
    });
  }
}

@Component({
  selector: 'app-tweet-dialog',
  templateUrl: './tweet-dialog.component.html'
})
export class TweetDialogComponent implements OnInit {
  private user: FirebaseObjectObservable<any[]>;

  constructor(
    public dialogRef: MdDialogRef<TweetDialogComponent>,
    private usersService: UsersService,
    private authService: AuthService) { }

  ngOnInit() {
    let uid = this.authService.getUser().uid;
    this.user = this.usersService.getUser(uid);
  }

}

The template is a simple as this atm

<h1>{{ (user | async)?.email }}</h1>

The user is stored in Firebase, and the problem is that for a brief moment the dialog window displays null until the user is retrieved. So I thought, ok, maybe is a good idea to retrieve the user in TweetService and pass it as a parameter to the TweetDialogComponent, but then I realized I don´t know how to do that.

I saw this angular2-material-mddialog-pass-in-variable and so I tried this

@Injectable()
export class TweetService {

  private dialogRef: MdDialogRef<TweetDialogComponent>;
  private user: FirebaseObjectObservable<any[]>;

  constructor(
    private dialog: MdDialog,
    private usersService: UsersService,
    private authService: AuthService) {
  }

  getUser(): FirebaseObjectObservable<any[]> {
    return this.user;
  }

  sendTweet(viewContainerRef: ViewContainerRef) {
    let config = new MdDialogConfig();
    config.viewContainerRef = viewContainerRef;

    let uid = this.authService.getUser().uid;
    this.user = this.usersService.getUser(uid);

    this.dialogRef = this.dialog.open(TweetDialogComponent, config);

    this.dialogRef.afterClosed().subscribe(result => {
      this.dialogRef = null;
    });
  }
}

@Component({
  selector: 'app-tweet-dialog',
  templateUrl: './tweet-dialog.component.html'
})
export class TweetDialogComponent implements OnInit {
  private user: FirebaseObjectObservable<any[]>;

  constructor(
    public dialogRef: MdDialogRef<TweetDialogComponent>,
    private tweetService: TweetService) { }

  ngOnInit() {
    this.user = this.tweetService.getUser();
  }

}

But that's giving me an error Can't resolve all parameters for TweetDialogComponent: (MdDialogRef, ?).

Any idea on how to do this? Thanks,

UPDATE

It seems this might be related with the order of imports in the barrels, but I'm not using barrels, I'm doing the imports directly from the file. This is my ngModule declaration (sorry, it's a bit long...)

@NgModule({
  declarations: [
    AppComponent,
    ProfileComponent,
    PeopleComponent,
    TimelineComponent,
    TweetDialogComponent,
    ProfilePipe
  ],
  entryComponents: [
    TweetDialogComponent
  ],
  imports: [
    routing,
    BrowserModule,
    AuthModule,
    AngularFireModule.initializeApp(firebaseConfig, firebaseAuthConfig),
    MaterialModule.forRoot()
  ],
  providers: [
    AUTH_PROVIDERS,
    AuthGuard,
    UsersService,
    { provide: TweetService, useClass: TweetService },
    { provide: LocationStrategy, useClass: HashLocationStrategy },
    { provide: APP_BASE_HREF, useValue: '/' }
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule {
}

TweetService is working fine in my AppComponent, so there shouldn´t be a problem with the provider. This is the sequence of imports in my TweetDialogComponent (I can´t see anything wrong).

import { Component, OnInit } from '@angular/core';
import { MdDialogRef } from '@angular/material/dialog';

import { FirebaseObjectObservable } from 'angularfire2';

import { TweetService } from '../../shared/services/tweet.service';

The structure of the project (for the affected component) is this:

src/app/
       /app.module.ts
       /app.component.ts
       /shared/services/
                       /tweet.service.ts
                       /users.service.ts
       /components/tweet-dialog/
                               /tweet-dialog.component.ts

Upvotes: 1

Views: 2608

Answers (1)

yurzui
yurzui

Reputation: 214017

You faced with a circular dependency. (TweetDialogComponent --> TweetService --> TweetDialogComponent)

You can work around by using an abstract class:

base-tweet.service.ts

import { ViewContainerRef } from '@angular/core';

export abstract class BaseTweetService {
  getUser() {};

  sendTweet(viewContainerRef: ViewContainerRef) {}
}

app.module.ts

{ provide: BaseTweetService, useClass: TweetService },

app.component.ts

constructor(
    ...
    private tweetService: BaseTweetService, 

tweet-dialog.component.ts

constructor(
  ...
  private tweetService: BaseTweetService) {  

tweet.service.ts

export class TweetService implements BaseTweetService {

See also

Upvotes: 2

Related Questions