Tips for effectively setting up your Angular project for success

Recently, I started working on a simple project:

https://stackblitz.com/edit/angular-rktmgc-ktjk3n?file=index.html

The main code resides in: /index.html

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<div class="mat-app-background basic-container">
    <br />
    <a href="https://material.angular.io/components/slide-toggle/api">API reference for Angular Material slide-toggle</a><br /><br />
    <select-reset-example>loading</select-reset-example>
    <div style="margin-top:30px;">
    <div style="color:#f00;margin-bottom:20px;">
          Here is what I am trying to achieve (not working as expected):
    </div>
        <mat-slide-toggle>Slide me!</mat-slide-toggle>
    </div>
</div>

The code snippet for: /app/select-reset-example.html

<mat-slide-toggle>Slide me!</mat-slide-toggle>

While loading the component: mat-slide-toggle within select-reset-example works fine, it doesn't work when trying to load it directly on index.html.

My query is regarding the configuration of the following /main.ts file to render the mat-slide-toggle directly on index.html.

In case there is a scope issue, is it feasible to create a custom component inheriting from mat-slide-toggle or MatSlideToggleModule class?

If possible, could you please fork the project on stackblitz.com and share the link with the necessary configuration?

import './polyfills';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatSlideToggleModule } from '@angular/material';
import { SelectResetExample } from './app/select-reset-example';
import { HttpModule } from '@angular/http';
import { CdkTableModule } from '@angular/cdk/table';

@NgModule({
  exports: [
    MatSlideToggleModule,
  ]
})
export class DemoMaterialModule { }

@NgModule({
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    FormsModule,
    HttpModule,
    DemoMaterialModule,
    ReactiveFormsModule,
  ],
  entryComponents: [SelectResetExample],
  declarations: [SelectResetExample],
  bootstrap: [SelectResetExample],
  providers: []
})
export class AppModule { }

platformBrowserDynamic().bootstrapModule(AppModule);

Here is the project structure for your reference:

https://i.sstatic.net/geeT3.png

Thank you!

Answer №1

There are various solutions that can be implemented in this scenario.

First Attempt

One way to solve the problem is by importing the MatSlideToggle component and adding it to the bootstrap array as shown below:

import { MatSlideToggle } from '@angular/material';

@NgModule({
  ...
  bootstrap: [SelectResetExample, MatSlideToggle ]
                                  ^^^^^^^^^^^^^^
                               This was quite simple!
})
export class AppModule { }

https://stackblitz.com/edit/angular-rktmgc-7h51hh?file=main.ts

However, it seems that this approach caused unexpected issues:).

Why?

Angular bootstraps the SelectResetExample component, which includes the mat-slide-toggle from the select-reset-example.html template. As a result, there are two mat-slide-toggle tags in the HTML.

When the second component (MatSlideToggle) is bootstrapped, it overlaps with the first mat-slide-toggle, causing the text Slide me! to disappear.

Second Attempt

Let's try changing the order of bootstrapping components:

@NgModule({
  ...
  bootstrap: [ MatSlideToggle, SelectResetExample ]
})
export class AppModule { }

https://stackblitz.com/edit/angular-rktmgc-mkm7ry?file=main.ts

The second slider now works, but unfortunately, we encountered the same issue of losing the text.

This problem arises because angular cannot handle projectable nodes during the bootstrapping process.

Third Attempt

We can override the bootstrapping process in Angular by utilizing the ngDoBootstrap method of the @NgModule. Let's give it a shot...

import { ApplicationRef, ComponentFactoryResolver, Injector, NgModuleRef } from '@angular/core';

@NgModule({
  // we replaced bootstrap option with entryComponents
  entryComponents: [SelectResetExample, MatSlideToggle],
})
export class AppModule { 
  constructor(
    private resolver: ComponentFactoryResolver,
    private ngModule: NgModuleRef<any>) {}

  ngDoBootstrap(appRef: ApplicationRef) {

    const factory = this.resolver.resolveComponentFactory(MatSlideToggle);
    const target = document.querySelector('mat-slide-toggle');
    const compRef = factory.create(
       Injector.NULL,
       [Array.from(target.childNodes)], // passing projectable nodes
       target, 
       this.ngModule);

    appRef.attachView(compRef.hostView);


    appRef.bootstrap(SelectResetExample);
  }
}

https://stackblitz.com/edit/angular-rktmgc-ncyebq?file=index.html

By bootstrapping our components through the custom ngDoBootstrap method, we were able to achieve success, but...

Do I really need to understand all this?

Probably not. There must be a simpler solution out there.

Fourth Attempt

To keep things uncomplicated, let's follow the design principles of the Angular framework by having a single root component. Let's create it:

app.component.ts

@Component({
  selector: '.mat-app-background.basic-container',
  templateUrl: './app.component.html',
})
export class AppComponent {
}

app.component.html

<br />
<a href="https://material.angular.io/components/slide-toggle/api">API reference for Angular Material slide-toggle</a><br /><br />
<select-reset-example>loading</select-reset-example>
<div style="margin-top:30px;">
  <div style="color:#f00;margin-bottom:20px;">
    Below is what I need to get it work like above (but it doesn't):
  </div>
  <mat-slide-toggle>Slide me!</mat-slide-toggle>
</div>

module

declarations: [SelectResetExample, AppComponent],
bootstrap: [AppComponent],

index.html

<div class="mat-app-background basic-container"></div>

I have moved the styles to external resources

Stackblitz Example

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Make an ajax request to a method in YII framework

I need to send an AJAX call to a function within the directory structure outlined below: Yii::$app->request->absoluteUrl."protected/humhub/modules/post/controllers/PostController/UploadMusicFile"; Here is my view function: function uploadImage ...

The declaration file for the module 'vue-html-to-paper' was not located

Struggling to make a sample project work with HTML to PDF, but encountering an error message stating: Could not find a declaration file for module 'vue-html-to-paper' Even though it resides in my node_modules index.js import Vue from 'vue& ...

Unable to physically tap on the checkbox input, though able to perceive the value it holds

When running my protractor test, I encountered an issue with the following statement: await element(by.model('publishCtrl.isPublishedInAllRegions')).click(); The test failed and returned an error message stating "ElementNotVisibleError: element ...

What could be causing this TypeScript code to not pass typechecking?

defining two objects in TypeScript with different property sets and assigning them to each other. Link to more information ...

How to effectively implement form-control with mat-radio-group?

UPDATE: Check out my code on stackblitz I'm facing an issue with my form layout. The form control rows are overlapping with the radio button rows. I need help to resolve this problem. Here is a snippet of my code: <form [formGroup]="formGroup" (n ...

What is the best way to position a popup div in CSS?

Currently, I am in the process of developing a website that displays DVD details when hovering over an image, similar to what is shown in picture 1. However, I've encountered an issue where the content gets cut off for DVDs located on the right side o ...

The ion-list will only load image URLs once the height has been established

I've been dealing with a technical issue that I don't have much experience in, and I'm struggling to find a solution. While I now understand the root cause of the problem, I am unsure how to resolve it. The webpage I am working on sends a r ...

Should the request be sent to the parent or child component?

When a page is divided into various components, the data for each component is fetched asynchronously. Therefore, the parent component should trigger the request and pass it on to the child component, or alternatively, the request can be directly sent to ...

Vue transition isn't functioning correctly without the specified mode parameter of 'out-in'

I'm struggling to comprehend why the transition doesn't smoothly roll from top to bottom without mode="out-in". When using out-in, it rolls as expected (albeit with a delay), but without it, the transition just suddenly appears after rolling dow ...

Tips for generating a fresh array by conditionally including an extra property based on the comparison of two arrays

I am working with two different arrays: lockers: [ { locker_id: 1, label: { size: 1, label: "small" } }, { locker_id: 2, label: { size: 3, label: "medium" } }, { locker_id: 3 ...

Leverage Node.js modules to reassign variable values

My simplified JavaScript module simulates an eye pose. var pose = {}; var eye = {}; var left = {}; left.pitchPos = 37; left.yawPos = 47; exports.init = function () { eye.left = left; pose.eye = eye; return this; }; exports.eye = function (e ...

Question about sending multiple Axios POST requests with parameters

I'm new to Stack Overflow and seeking help with a specific issue on my Rails backend and Vue.js frontend website. The challenge I'm facing involves making two POST requests simultaneously when the submit button is clicked. My "Trips" controller ...

Utilizing numerous await statements within a single asynchronous function

My async function has 3 awaits, like this: const sequenceOfCalls = async(req, res, next) =>{ await mongoQuery(); await apiCall1(); await apiCall2(); } apiCall1 uses response of mongoQuery and apiCall2 uses response of apiCall1. The issue is ...

Encountering an Error in Laravel 8: Form Submission Issue - Uncaught TypeError Preventing Property Read

<a href="{{ url('/home') }}">Home</a> <a href="{{ route('logout') }}" onclick="event.preventDefault();document.getElementById('logout-form').submit();">Logout</a> <form ...

Issue with express-http-proxy where relative URL paths are not functioning as expected

My server is hosting an app along with a few simple web microservices. I want to access these services over the internet without having to open individual ports for each one. To achieve this, I decided to set up a reverse proxy on the server using express- ...

"Exploring the world of remote_form_tag in Rails with jrails

After transitioning to jQuery with jRails for my application, most of my previous RJS code is working perfectly. However, I am facing an issue with the :loading => callback when using the remote_form_tag. <% form_remote_tag :url => '/hostels ...

Tips for establishing communication between a React Native webView and a React web application

I am currently working on establishing communication between a webView in react-native and a web-app created with React-360 (and React). I am utilizing the react-native-webview library and following a guide for creating this communication. You can find the ...

Angular application featuring scrolling buttons

[Apologies for any language errors] I need to create a scrollable view with scroll buttons, similar to the image below: Specifications: If the list overflows, display right/left buttons. Hide the scroll buttons if there is no overflow. Disable the le ...

Strange Angular NPM package conflict causing error

Encountering a strange issue with npm. Even after deleting node modules, package-lock.json, and running npm cache clean --force, attempting npm install results in the following error message- Could not resolve dependency: npm ERR! peer @angular/com ...

AngularJS view is not refreshing

I am facing an issue with updating a view via a controller that fetches data from a service. Despite changing the data in the service, the view does not reflect these updates. I have created a simplified example from my application, which can be found here ...