#routerLink does not render the page

41 messages · Page 1 of 1 (latest)

rare hare
#

Hi,
I'm calling a page to edit some data. I use routerLink to call up the page. However, when clicking the data is not loaded in the form. The data appears in the inputs only after I refresh the page. How do I fix this?

gusty kernel
#

My first guess is that you didn't import RouterModule

#

g!codeblock @rare hare But without an error message nor code, all I can do is guess. Post that for better help

hollow stoneBOT
#

@rare hare, you can use the following snippet to have your code formatted and colored by Discord. Replace ts with the language you need (i.e. html, js, css, etc)
```ts
// your code goes here
```

rare hare
gusty kernel
#

code

#

My 2nd guess is that you are using a snapshot instead of observing on the route params

rare hare
#

when I call my page html <button mat-menu-item type="button" routerLink="profile"> <mat-icon>person_pin</mat-icon> <span>Meu Perfil</span> </button>

rare hare
#

Want to see my route code? I'm loading correctly

gusty kernel
#
interface ViewModel {
  requirePassword: boolean;
  user?: IUser;
}

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: [ './profile.component.css' ],
})
export class ProfileComponent extends Toolbar implements OnInit {
  public readonly vm$: Observable<ViewModel>;

  //Fomrulário
  public readonly form: FormGroup;

  constructor(
    private readonly authService: AuthService,
    private readonly title: Title, 
  ) {
    super(); // This is really not a good idea IMPO.

    this.form = new FormGroup({
      id: new FormControl(''),
      name: new FormControl('', [ Validators.required, Validators.maxLength(255) ]),
      email: new FormControl('', [ Validators.required, Validators.maxLength(255), Validators.email ]),
    });

    this.vm$ = this.authService.getLoggedUser().pipe(
      tap((user?: IUser): void => {
        if (user) {
          this.form.reset(user);
        }
      }),
      map((user?: IUser): ViewModel => ({
        requirePassword: Boolean(user),
        user,
      })),
    );
  }

  ngOnInit(): void {
    this.title.setTitle('Dativos | Meu Perfil');
    this.breadcrumbs = [ 'Meu Perfil' ];
  }

  public onSubmit() {
    console.log(this.form.value);
  }
}
rare hare
gusty kernel
#
<app-toolbar [breadcrumbs]="breadcrumbs" [buttons]="buttons" (clickButtonEvent)="clickToolbar($event)"></app-toolbar>

<form *ngIf="vm$ | async as vm; else loading" [formGroup]="form" (ngSubmit)="onSubmit()">
  <input type="hidden" formControlName="id">
  <mat-sidenav-container hasBackdrop="true">
    <div class="component-content">
      <mat-card>
        <mat-card-title><strong>Meu Perfil</strong></mat-card-title>
        <mat-card-content>
          <mat-form-field appearance="legacy">
            <mat-label>E-Mail</mat-label>
            <input matInput placeholder="[email protected]" formControlName="email" autocomplete="off" max="255" required>
            <mat-icon matSuffix>mail_outline</mat-icon>
          </mat-form-field>
          <mat-form-field appearance="legacy">
            <mat-label>Nome</mat-label>
            <input matInput placeholder="Joaquim José da Silva Xavier" formControlName="name" autocomplete="off" max="255" required>
            <mat-icon matSuffix>person_outline</mat-icon>
          </mat-form-field>
          <div>
            <app-input-pass [subForm]="form" [require]="vm.requirePassword"></app-input-pass>
          </div>
          <mat-divider></mat-divider>
          <mat-card-actions>
            <button class="button-block" type="submit" mat-flat-button color="primary">Atualizar</button>
          </mat-card-actions>
        </mat-card-content>
      </mat-card>
    </div>
  </mat-sidenav-container>
</form>
<ng-template #loading><div>Loading...</div></ng-template>
#

this is good: user$: Observable<IUser>;

No. This is not an @Input, and you already have an observer of user. Don't do this: @Input('user') user?: IUser;

Don't .subscribe to get values out of an Observable. Use the AsyncPipe.

  /**
   * Carrega os dados do usuário
   */
  private loadMyUser() {
    this.user$.subscribe({
      next: user => {
        if (user.abilities) {
          this.user = user;
          console.log(this.user);
        }
      }
    });
  }
#

So I put all of the data you need for the view, into a Model for the View: a ViewModel

#

Initializing the form's values from an Observable can be tricky. It is a side effect (https://en.wikipedia.org/wiki/Side_effect_(computer_science)) so in RxJS you use tap (https://rxjs.dev/api/operators/tap) to perform side effects like initializing the Form.

In computer science, an operation, function or expression is said to have a side effect if it modifies some state variable value(s) outside its local environment, which is to say if it has any observable effect other than its primary effect of returning a value to the invoker of the operation. Example side effects include modifying a non-local v...

rare hare
gusty kernel
#

Then I added *ngIf="vm$ | async as vm" to your <form> so you could get the values out of the Observable.

gusty kernel
#

All the things you do to an Observable's emissions (the values that come from/out of an Observable) should be inside a .pipe()

#

You had a side effect (discussed above) and you needed to convert the user into a ViewModel (because you needed to know if the user was truthy to decide if require password was true).

#

Now you could have just done: This is wrong 😦

<form *ngIf="user$ | async as user" [formGroup]="form" (ngSubmit)="onSubmit()">
  <app-input-pass [subForm]="form" [require]="user != null"></app-input-pass>

But I think that the ViewModel is more expressive and easier to read. As was your use of isRequirePassword.

#

Actually ☝️ this wouldn't work because if user was null then *ngIf would hide the form.

#

Oh, and I've added the loading thing above now.

<form *ngIf="vm$ | async as vm; else loading" [formGroup]="form" (ngSubmit)="onSubmit()">
</form>
<ng-template #loading><div>Loading...</div></ng-template>
rare hare
gusty kernel
#

IIRC you didn't have any *ngIf before. your problem was that you didn't think Asynchronously.

rare hare
gusty kernel
#

In your constructor you tried to initialize the form:

  //Dados
  @Input('user') user?: IUser;

  constructor() {
    super();
    this.user$ = this.authService.getLoggedUser();
    this.form = new FormGroup({
      id: new FormControl(this.user ? this.user.id : ''),
#

But this.user wasn't set yet.

#

especially not set yet because

  ngOnInit(): void {
    this.loadMyUser();

Happens after the constructor.

#

But triply not set because

    this.user$.subscribe({
      next: user => {
        if (user.abilities) {
          this.user = user;
          console.log(this.user);

the next method happens billions of processor instructions after ngOnInit which is further thousands of processor instructions after constructor

#
  1. constructor is invoked
  2. 1000s of instructions later
  3. ngOnInit is invoked
  4. Billions of instructions later, from your Processor's view weeks will pass
  5. the .subscribe next method is invoked.
rare hare
#
super(); // This is really not a good idea IMPO.``` Why is not a good idea?
gusty kernel
rare hare
#

@gusty kernel Thank you for your help! 🙏🏿
The other thread that you also helped me with worked as well.

gusty kernel
#

Jeff Atwood (2007) - Your Code: OOP or POO?
"OO seems to bring at least as many problems to the table as it solves."

Eric Allman (2011) - Programming Isn't Fun Any More
"I used to be enamored of object-oriented programming. I'm now finding myself leaning toward believing that it is a plot designed to destroy joy. The methodology looks clean and elegant at first, but when you actually get into real programs they rapidly turn into horrid messes."

[Richard Mansfield] - WhitePaperHasOOPFailed.pdf (http://4js.com/files/documents/products/genero/WhitePaperHasOOPFailed.pdf)

OOP has taken over computer "science" departments to the exclusion of any alternative programming system. A generation of programmers has graduated from schools that teach only the OOP way, so that’s what they tend to prefer. It's really all they know. They memorize a set of “best practices” (abstract design rules) to help them grind out OOP without making too many mistakes. OOP can be effective to some extent during the initial design phase--when a program’s broad goals and large-scale structure is being imagined and sketched in. However, for day-do-day code writing, OOP is generally the single biggest obstacle to contemporary programmer productivity. Are results achieved faster? No, creating programs usually takes considerably longer than it does with more natural languages and more sensible approaches to modular design. Have bugs been reduced? No, they usually increase. Is program maintenance easier? No, OOP and C languages are notoriously counterintuitive and difficult to read.

rare hare
#

!Close

gusty kernel
#

But there is no need. 24 hours later and Discord will automatically close this