When accessing a method exposed in Angular2 from an external application, the binding changes are lost

In my code, I have a method that is made public and accessible through the window object. This method interacts with a Component and updates a variable in the template. However, even after changing the value of the variable, the *ngIf() directive does not trigger.

Here is a snippet from app.component:

constructor(private _public: PublicService,) {
        window.angular = {methods: this._public};
    }

This is the PublicService class:

export class PublicService {

    constructor(
        private  _viewManager: ViewManagerComponent,
    ) {}

    CallMe(){
        this._viewManager.renderView('page1')
    }
}

And here is the ViewManagerComponent:

@Component({
    selector: 'view-manager',
    template: `<page *ngIf="view == 'page1'"></page>`
})
export class ViewManagerComponent {
    
    view = "page";

    renderView = function(type){
        console.log(type)
        this.view = type;
        console.log(this.view)
    };
}

The intended functionality is that initially, the page renders blank. When calling angular.methods.CallMe(), it should update the view variable to 'page1' and display the corresponding HTML content. Despite successfully calling the renderView function, the view does not change as expected.

----Update - Still facing issues -------

export class ViewManagerComponent {
    constructor(private zone:NgZone,private cdRef:ChangeDetectorRef) {
        
    }
    view = "page";

     @Output() renderView(type){
        console.log(this.view);
        this.zone.run(() => {
            console.log(this.view);
            this.view = type;
            console.log(this.view);
        });
        console.log(this.view);
        //cdRef errors: 
        //view-manager.component.ts:36 Uncaught TypeError: this.cdRef.detectChanges is not a function(…)
        this.cdRef.detectChanges();
    };

}

Answer №1

When changes are made outside of Angular's zone, Angular2 may not automatically detect and run change detection. To explicitly trigger change detection, you can use the following method:

Explicitly Run Change Detection

constructor(private cdRef:ChangeDetectorRef) {}

someMethodCalledFromOutside() {
  // Code that alters properties in this component 
  this.cdRef.detectChanges();
}

To ensure that code modifying the component's properties is executed within Angular's zone, use the following approach:

constructor(private zone:NgZone) {}

someMethodCalledFromOutside() {
  this.zone.run(() => {
    // Code that alters properties in this component
  });
}

The zone method is preferred when the code not only affects properties of the current component but also influences other components. This way, changes triggered by this call will be detected without explicitly handling change detection in each affected component.

Using function(...) instead of () => may lead to unexpected behavior with this inside the Angular component.

For further information, refer to my response to a related question here: Angular 2 - communication of typescript functions with external js libraries

Update

export class ViewManagerComponent {
    constructor(private zone:NgZone,private cdRef:ChangeDetectorRef) {
      self = this;
    }
    view = "page";

     @Output() renderView(type){
        // type is 'page'
        console.log(self.view)
        self.zone.run(() => {
            // type is 'page'
            console.log(self.view)
            self.view = type;
            // type is 'page1'
            console.log(self.view)
        });
        // type is 'page1'
        console.log(self.view)
        self.cdRef.detectChanges();
    };

}

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

Tips for making WebDriver pause until Sencha AJAX request finishes

While testing a page with Selenium WebDriver, I encountered an issue related to the Sencha JavaScript library being used on the underlying page. The problem arises when I input a value into a field and an AJAX call is made to validate that field. If the va ...

Struggling to pass a function argument as a string for use within the function

Although the title may seem unclear, I will clarify. I have a collection of images on the left side and I have implemented an onclick function on each one to display the image and some information on the right side. It's like having thumbnails on the ...

Mastering the art of redirection in Node.js

Encountering an issue with redirecting between directories - having trouble directing to another file in a different directory. Here is my directory structure: -views -add_user.jade -routes -index.js Attempting to redirect to add_user.jade from inde ...

Tips for resolving the issue of loading not appearing on screen in Angular

How can I resolve the problem of the loading animation not appearing? Below is the code snippet: HTML <div *ngIf="tempThermometer | async as temp; else loading"> <ng-container *ngIf="temp.length !== 0; else noItems"> &l ...

managing, modifying and removing information within the app.controller in AngularJS

I am currently facing a challenge with my Javascript code for a simple web application that involves AngularJS. Here is the snippet of code I am working on: app.filter('startFrom', function () { return function (input, start) { if (i ...

Prefixes for logging - Consider using the not-singleton technique or another approach

I am currently developing a logging helper for Node.JS that includes several exported functions such as error and warn. For instance, I have two other scripts called test1 and test2 which make use of this "module". When initializing my logging module us ...

Modify the behavior of the tab key using JavaScript

I'm currently working on a text editor embedded within a contenteditable div. My goal is to modify the [TAB] functionality so that instead of shifting focus to the next element (as is done by default in browsers), it will either insert spaces or a &b ...

Universal Angular along with Window's Innerwidth

Utilizing Window.Innerwidth in my Angular Project has been successful, however, I encountered an issue when attempting to implement it into Angular Universal. The content within window.innerwidth does not appear in the view source. Here is a snippet of my ...

Transforming a non-specific type into a container permits precarious assignments

I'm encountering an issue with the code snippet provided below. Despite having a specific type where Type<boolean> cannot be assigned to Type<true>, when wrapping it in an object type (BoxType as shown), suddenly BoxType<boolean> wro ...

Master the art of adjusting chart width on angular-chart with the help of chart.js

I am currently using angular-chart along with Angular and chart.js to create multiple charts on a single page. However, I am facing an issue where each chart is taking up the entire width of the screen. I have tried various methods to limit the width based ...

The optimal method for storing tokens in Vue when using Laravel Sanctum

I am currently working on an application built with Laravel and Vue.js. My current focus is implementing the login/logout functionality using Laravel Sanctum. Here is my scenario: I already have the backend methods for login/logout/register set up, but I ...

Enhance user experience with jQuery UI sortable and the ability to edit content in real

I am facing an issue with jquery sortable and contenteditable. The problem arises when I try to use jquery sortable along with contenteditable, as the contenteditable feature stops working. After searching on Stack Overflow, I found a solution. However, up ...

Using Typescript generics within a callback function

I am currently working on developing a versatile service that can fetch data from a remote source and create objects based on that data. @Injectable() export class tService<T> { private _data: BehaviorSubject<T[]> = new BehaviorSubject([]) ...

Use JavaScript to upload a JSON file containing arrays into separate tabs

Looking for help with incorporating JSON data into an HTML template that features tabs and a gallery? Take a look at my setup below: <div class="tab"> <button class="tabLinks" onclick="openDiv(event, 'overview'); appendData()" id= ...

Regular expressions are compatible with JavaScript, but unfortunately, they are not supported

After successfully implementing this regex in my JavaScript for webpage validation, I attempted to incorporate it into my PHP script as a backup. However, every string I passed through the regex failed, even correct names. In an effort to resolve the issu ...

Avoiding the duplication of selected items in a dropdown within a gridview can be achieved effectively by implementing a JavaScript/jQuery

In my gridview, which contains multiple rows, each row has a dropdown (select in HTML). My goal is to prevent the user from selecting the same item from the dropdown list for different rows. For instance, if a user selects "New York": Assigning rooms: U ...

Utilizing query parameters in Next.js

I've been working on a unique Next.js application that incorporates both infinite scroll and a search input feature. The infinite scroll functionality loads 6 additional items whenever the user reaches the bottom of the page. On the other hand, the s ...

Utilize promise-style for Sequelize associations instead, please

I am in the process of merging information from 3 tables - Products, Suppliers, and Categories. My goal is to retrieve the row with SupplierID = 13. I recently came across a helpful explanation on How to implement many to many association in sequelize, whi ...

Implementing concurrent operations in React Native using Firebase, combining async/await with Promise.all

import fire from '../config/fire'; const db = fire.firestore(); class InitialDb extends Component { constructor(props) { super(props); this.state = { schools: '', students: '', }; } async compo ...

Guide to loading a minified file in Angular 2 with Gulp Uglify for TypeScript Bundled File minimization

In my Angular 2 application, I have set the TypeScript compiler options to generate a single outFile named Scripts1.js along with Scripts1.js.map. Within my index.html file: <script src="Scripts/Script1.js"></script> <script> ...