Tuesday, November 16, 2021

Architectures with Angular Libraries, NX and Monorepos

 

  • explain the power of Angular's architectural features
  • push them to the edge where the extraction of libraries and creating a complete workspace with tools like NX can save you
  • help you to write clean large Angular applications
  • get your Angular business application back into shape again.
Because large angular apps don't have to be difficult to maintain.

Friday, November 12, 2021

Angular @ViewChild() error: Expected 2 arguments, but got 1


Below Here given solution. 

 In Angular 12 , ViewChild takes 2 parameters

@ViewChild(ChildDirective, {static: false}) Component

Wednesday, November 10, 2021

What is difference between disabling a form control through reactive forms API and HTML attributes

 Below is a simple form with two fields and a button. We will use this setup to illustrate the different ways to disable form controls.

Here’s how we create this form in our application’s code:

Form component class


@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit { form: FormGroup; constructor(private formBuilder: FormBuilder) { } ngOnInit(): void { this.form = this.formBuilder.group({ firstName: [{ value: 'Foo', disabled: true }, [Validators.required]], lastName: ['Bar'] }); } onSubmit(): void { } get firstName(): FormControl { return this.form.controls.firstName as FormControl; } get lastName(): FormControl { return this.form.controls.lastName as FormControl; } }

Note that in the component class I have defined accessors to the two form controls for the ease of access.

Form template

<form [formGroup]="form">
 <h1>Angular Reactive Form</h1>
 <input formControlName="firstName" placeholder="First Name" />
 <input formControlName="lastName" placeholder="Last Name" />
 <button (click)="onSubmit()">Submit</button>
</form>

I’m using formGroup and formControlName directives from Reactive Forms API here.

Using the FormControl’s disable() instance method

This method will disable both the UI control and the FormControl’s instance. Let us see how we’d use this method to disable a form control. In the ngOnInit function,  after creating the form instance, we can disable the lastName form control like below.


ngOnInit(): void { this.form = this.formBuilder.group({ firstName: [{ value: 'Foo', disabled: true }, [Validators.required]], lastName: ['Bar'] }); this.lastName.disable(); }

If we console.log the control lastName we’ll see its instance will be disabled.

Showing the affected properties for a disabled form control

This way is quick and straightforward.

When would this way of disabling FormControls be a disadvantage?

When we depend on a FormGroup’s validity status to make some decisions. Let’s see how, let’s change our ngOnInit code a bit by adding console logs.


ngOnInit(): void { this.form = this.formBuilder.group({ firstName: [{ value: 'Foo', disabled: true }, [Validators.required]], lastName: ['Bar'] }); this.lastName.disable(); console.log(this.lastName); console.log('Form:::', this.form); }

We’ve given the form controls default values, disabled both the controls and required the firstName control by having a required validator on its configuration. Note that the firstName control is disabled by default.

The last console.log’s output is below.

Showing how having all controls disabled in a form group affects the forms status and validity

Something worth noting is that when we have all form controls disabled, irrespective of their validity status', the controls' instance status properties will be set to "DISABLED" hence the FormGroup's status will also be set to "DISABLED".

In the log snippet above, can you also see that the form’s valid and invalid properties are both false, but the controls have values and are valid? Can you see the confusion this way of disabling controls might cause when the form’s validity is a dependency in some decisions we have to make?

For example, let's say we have a big form implementation and we are aware that some form fields will need to be disabled.

For instance, say we have a second form in a separate page that requires the firstName and lastName the user had entered in the first form. We would, in the second form, disable and pre-populate the firstName and lastName inputs; now let’s say we want to propagate the form’s value to some state store when the form value or status changes but when the form is valid.

Let’s consider a case where we have a listener to the form value changes and we have some controls whose values are changed by an external source.


this.form.valueChanges .pipe( distinctUntilChanged() ) .subscribe( (status) => { if (this.form.status === 'VALID') {// `this.form.status` is "DISABLED" // set some state value } } ); this.lastName.setValue('Baz');

We set an observer to the form’s value changes and after we change the value of the lastName control.

Our form’s value will not sync with our application state store because when the observer executes, it will find that the form’s status is DISABLED even though the form value is valid which might cause confusion and discrepancies in our code especially when the state store has observers to it also.

That could be an issue with this mechanism of disabling form controls.

Another way to disable form controls is the one we use to disable the firstName control when instantiating the form itself.


this.form = this.formBuilder.group({ firstName: [{ value: 'Foo', disabled: true }, [Validators.required]], lastName: ['Bar'] });

This has the same effect described above when a control is disabled using the .disable() control method.

Using a template attribute to disable FormControls

Yet another way is to add disabled=true attribute to HTML in the template like this:


<form [formGroup]="form"> <h1>Angular Reactive Form</h1> <input formControlName="firstName" placeholder="First Name"> <input formControlName="lastName" disabled="true" placeholder="Last Name"> <button (click)="onSubmit()">Submit</button> </form>

Which gives the below warning

This warning is thrown to warn you about the potential errors regarding "changed after checked" that might be thrown in result of using the disabled attribute directive with a reactive form.

What this means is that, if the disabled attribute would expect a dynamic expression like [disabled]="isDisabled"   (resulting in true or false, not just a static true for example) resulting in a binding eligible for being checked during change detection, it would make the binding susceptible to the "changed after checked" error, that is, the expression could be false when change detection is run and then true when the change detection verification phase runs.

A deep dive into the ‘ExpressionChangedAfterItHasBeenCheckedError’ error can be found here .

So to avoid the warning, you can use the [attr.*] binding like this:


<form [formGroup]="form"> <h1>Angular Reactive Form</h1> <input formControlName="firstName" placeholder="First Name"> <input formControlName="lastName" [attr.disabled]="true" placeholder="Last Name"> <button (click)="onSubmit()">Submit</button> </form>

There’s no warning, but it is worth noting that this will add the HTML disabled attribute which cannot be toggled using just true and false (as false also results in a disabled field), null and undefined can be used to enable the field. Another way to enable a field with this attribute with value set to true, false or any truthy value is by removing it from the field.

Both approaches have the same outcome, a form with a status of VALID, which is what we want to offset the limitation that comes with using the first approach described above (Using the FormControl’s disable() instance method).

The form's value is missing the firstNames' property and value

However, it is important to note the form’s value does not have the firstName’s control value because it is disabled, this happens when some of the form controls are disabled (Using the FormControl’s disable() instance method or from the form configuration like for the firstName control) and some are enabled or disabled using the [disabled] template directive.

To circumvent this issue, we can use a form’s instance method to get the raw form value that will include values of disabled controls on the form.


this.form.getRawValue()

console.log(this.form.value); console.log(this.form.getRawValue()); // The logs will have
The results of using a FormGroup's .value and getRawValue properties

With the second approach (Using a template attribute to disable FormControls) we can expect what we see on the form UI to mirror the value of the form’s instance without affecting the controls instances.

Another way similar to the latter ([attr.disabled]) is to use the readonly attribute.


<form [formGroup]="form"> <h1>Angular Reactive Form</h1> <input formControlName="firstName" placeholder="First Name"> <input formControlName="lastName" readonly="true" placeholder="Last Name"> <button (click)="onSubmit()">Submit</button> </form>

This one has the same effect as using the disabled attribute but does not apply disabled visuals to the control, this will disable the input control but to the eye it will look like the control is enabled.

You can simply style the input like below.


input { margin-bottom: 8px; width: 250px; height: 45px; border-radius: 3px; padding-left: 10px; border: 1px solid rgba(0, 0, 0, 0.4); &:read-only { color: rgb(84, 84, 84); cursor: default; background-color: rgba(239, 239, 239, 0.3); &:focus { outline: none; } } }

Those are the differences I have experienced with the different ways of disabled form controls.

In conclusion

We have seen the different ways we can use to disable form control. They are the following:

  • Using the FormControl’s disable() instance method
  • Disabling a FormControl from the form configuration
  • Using a template attribute to disable FormControls like disable[attr.disable] and readonly

We have also seen how the first two approaches can affect the form’s status value (Which could possibly affect the application state if it is synced with the form’s state).
Depending on your requirements and use case, it is beneficial to consider beforehand the approach that will not limit your flexibility when working with reactive forms.

Saturday, November 6, 2021

window is not defined angular | SSR | Solution

 You can fix window is not defined like this:

  server.ts (start of file)

const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync(path.join(__dirname, '.', 'dist', 'index.html')).toString();
const win = domino.createWindow(template);
global['window'] = win;
global['document'] = win.document;

How to build an Express and Node.js app with Typescript

  In this tutorial, you will learn how to set up a Node.js and Express project with Typescript and live auto-reloading. Note that this metho...