Open pjpsoares opened 8 years ago
+1
Mine may be a different issue but it sounds very similar. It is probably related to #93 too ..
I am building my form with a couple of *ngForm=
directives and one field has a prefilled value. The values are bound to a common datastore service with [(ngModel)]=
directives. I have four pages with routing. If the page with the prefilled formfield is the one to be loaded first, then everything is fine. If I then navigate to another page and back the form page, then all labels overlap the filled in values.
What I get:
What I expect (and get, after I clicked into the field at least once after pageload): (The date field is a textfield here, for sake of simplicity.)
Some code to reproduce:
<div materialize *ngFor="let field of fields.group">
<div class="input-field col" [ngClass]="field.type === 'area' ? 's12' : 's6'">
<!-- show textarea or simple input field based on type -->
<textarea *ngIf="field.type === 'area'" [id]="'orderform-' + field.id" [(ngModel)]="field.data"
(ngModelChange)="fieldstore.rehash()" class="materialize-textarea validate"></textarea>
<input *ngIf="field.type === 'field'" [id]="'orderform-' + field.id" [(ngModel)]="field.data"
(ngModelChange)="fieldstore.rehash()" type="text" class="validate">
<label [id]="'orderform-' + field.id" class="active"> {{ field.label.de }} </label>
</div>
</div>
As stated in #93, manually setting the active class with an [ngClass]=
doesn't work either ..
I am currently migrating my project to the Angular 2.0.0 release and did not have this issue with RC.3 before.
@pjpsoares Set the class on the label to active
I'm having the same problem that @ansemjo
I have moved to using FormControls and haven't had this problem since. They are also a lot more powerful than simple ngModels and actually the latter uses FormControls under the hood anyway.
Example Code:
<div
class="input-field col s12"
[ngClass]="field.textarea ? 'm12' : 'm6'"
>
<!-- show textarea or simple input field based on type -->
<textarea *ngIf=" area" [id]="id" [formControl]="formcontrol"
class="validate materialize-textarea"></textarea>
<input *ngIf="!area" [id]="id" [formControl]="formcontrol"
class="validate" type="text" />
<!-- materialize animated label -->
<label [id]="id"> {{ label.german }} </label>
</div>
import { Component, Input, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Order } from '@app/classes';
/** A single input field for orderform data. */
@Component({
selector : 'inputfield',
templateUrl : 'inputfield.component.html'
})
export class OrderInputFieldComponent implements OnInit {
/** orderdata field to map */
@Input() field: Order.Field;
/** formcontrol observable */
readonly formcontrol = new FormControl();
/* set initial value and subscribe to changes */
async ngOnInit() {
this.formcontrol.setValue(this.field.value);
this.formcontrol.valueChanges
.debounceTime(200)
.subscribe(value => this.field.value = value);
}
/** unique DOM id */
get id () { return `orderform-${this.field.uuid}`; }
/** field label */
get label () { return this.field.label; }
/** field is a textarea */
get area () { return this.field.flags.textarea; }
}
Hope that helps.
I have changed to ReactiveForm and still with the same problem
Did any one found a good solution for this problem ?
I'm actually using the following workaround :
declare var Materialize:any;
export class MyComponent implements OnInit, AfterViewChecked {
...
ngAfterViewChecked() {
Materialize.updateTextFields();
}
}
The idea is to call Materialize.updateTextFields()
; after the dom initialization.
@RadouaneRoufid proposal worked for me. Thank you very much.
Nevertheless, a cleaner solution is needed in order to not including this code in every single component with a form.
Neither solution works for me. I have the label's active class set: but when the component finishes loading, it is unset.
I also tried @RadouaneRoufid's solution, but it generates an error.
Even though it is clearly a function.
Interestingly enough, the error only occurs on a refresh. If I navigate to the item from another route, it works fine. If I refresh the page on that route, either directly through the browser or via auto-refresh from ng
on save, the error occurs.
edit: is it possible the issue is related to ngAfterViewChecked()
on a new page load? Like, maybe the assets aren't being loaded before the view is checked? In the button example, you're calling updateTextFields()
on a button click, presumably after all assets and views have been loaded.
$('.input-field label').addClass('active');
setTimeout(function(){ $('.input-field label').addClass('active'); }, 1);
Back to this problem !
The solution I proposed early works great but it's not good for performance. It's quite heavy because you have to implement AfterViewChecked lifecycle for each component and sometimes it does not work on first initialization.
Another solution which works is to execute updateTextFields on each route event on the main component AppComponent. :
declare var Materialize: any;
declare let $: any;
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
public ngOnInit(): void {
this.router.events.subscribe(evt => {
$(document).ready(() =>
setTimeout(() => {
Materialize.updateTextFields()
}, 10)
);
if (!(evt instanceof NavigationEnd)) {
return;
}
window.scrollTo(0, 0);
});
}
}
When you have an input text that has the label being pushed to the top, on focus, (http://angular2-materialize.surge.sh/#/forms the last name input), if you have an ngModel setting the value, it won't push automatically to the top, overlaping both the label and the input value.