The HTML button triggers a function to execute on a different webpage when clicked

I'm facing a straightforward issue that I can't seem to figure out due to my limited experience with Angular and web development. The problem revolves around two components, namely home and dashboard. In the home.component.html file, there's a button that toggles the image source from bulbOn.png to bulbOff.png. What I want is for this button to change the image source in the same way on the dashboard.component.html file as well. I believe I need to use TypeScript for this task, but I'm unsure how to go about it. Essentially, how can an onClick event in one HTML trigger actions in another HTML?

home.component.html

<mat-card >              
              <button onclick="document.getElementById('myImage').src='assets/BulbOn.svg'">Turn on the bulb.</button>
              
              <img id="myImage" src="assets/BulbOn.svg" style="width:100px">
              
              <button onclick="document.getElementById('myImage').src='assets/BulbOff.svg'">Turn off the bulb.</button>
              
              </mat-card>

dashboard.component.html

<mat-card class="bulbCard">
    <div class="bulbimg"> <img src="assets/BulbOn.svg"> </div>
    </mat-card>

dashboard.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.less']
})
export class DashboardComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}

home.component.ts

import { Component } from '@angular/core';
import { User } from '@app/_models';
import { AccountService } from '@app/_services';

@Component({ templateUrl: 'home.component.html',
styleUrls: ['./home.component.less'] })
export class HomeComponent {
    user: User;

    constructor(private accountService: AccountService) {
        this.user = this.accountService.userValue;
    }
}

Answer №1

A best practice is to refrain from directly manipulating the DOM in Angular.

Instead of using onclick, it's recommended to utilize Angular's event binding capabilities. https://angular.io/guide/event-binding

<mat-card>              
    <button (click)="changeBulbState(true)">
        Turn on the bulb.
    </button>
              
    <img [src]="bulbState ? 'assets/BulbOn.svg' : 'assets/BulbOff.svg'" style="width:100px">
              
    <button (click)="changeBulbState(false)">
        Turn off the bulb.
    </button>
              
</mat-card>

Include a variable for bulbState in your component's TypeScript file. This variable will be updated as you interact with the buttons on your card.

The image source will dynamically change based on the value of the bulbState variable.

import { Component } from '@angular/core';
import { User } from '@app/_models';
import { AccountService } from '@app/_services';

@Component({ templateUrl: 'home.component.html',
styleUrls: ['./home.component.less'] })
export class HomeComponent {
    user: User;

    bulbState: boolean;

    constructor(
        private accountService: AccountService,
        private bulbStatusService: BulbStatusService
    ) {
        this.user = this.accountService.userValue,
        this.bulbStatusService.bulbStatus.subscribe(data => this.bulbState = value)
    }

    changeBulbState(state: boolean) {
        this.bulbStatusService.changeBulbState(state);
    }

}

To share functionality across multiple components, consider using a service.

https://medium.com/front-end-weekly/sharing-data-between-angular-components-f76fa680bf76

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable()
export class BulbStatusService {

  private bulbState = new BehaviorSubject(false);
  bulbStatus = this.bulbState.asObservable();

  constructor() { }

  changeBulbState(state: boolean) {
    this.bulbState.next(state)
  }
  
}

Answer №2

To achieve the desired functionality, it is important to establish a state for the bulb somewhere in an Angular application. This can be done by either having the parent component pass down the state to its children or utilizing a service to manage the state. Luckily, Angular comes equipped with RxJS which provides powerful utilities like observables for sharing states.

For example, consider creating an app-state.service.ts file:

import { BehaviorSubject } from 'rxjs'; 

@Injectable({
  providedIn: 'root'
})
export class AppState {
   public readonly lightBulb = new BehaviorSubject<'on' | 'off'>('on');
}

You can then inject this service into your home component:

import { Component } from '@angular/core';
import { User } from '@app/_models';
import { AccountService } from '@app/_services';
import { AppState } from 'app-state.service';

@Component({ templateUrl: 'home.component.html',
styleUrls: ['./home.component.less'] })
export class HomeComponent {
    user: User;

    constructor(
        private accountService: AccountService,
        public state: AppState
    ) {
        this.user = this.accountService.userValue;
    }
}

In the HTML template:

<mat-card>              
  <button (click)="state.lightBulb.next('on')">Turn on the bulb.</button>
  <img id="myImage" [src]="(state.lightBulb | async) === 'on' ? 'assets/BulbOn.svg' : 'assets/BulbOff.svg'" style="width:100px">
  <button (click)="state.lightBulb.next('off')">Turn off the bulb.</button>
</mat-card>

Repeat this process for the dashboard component as well:

import { Component } from '@angular/core';
import { AppState } from 'app-state.service';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.less']
})
export class DashboardComponent {

  constructor(public state: AppState) { }
}

And in the dashboard's HTML:

<mat-card class="bulbCard">
    <div class="bulbimg"><img [src]="(state.lightBulb | async) === 'on' ? 'assets/BulbOn.svg' : 'assets/BulbOff.svg'"></div>
</mat-card>

In summary, Subjects are containers that hold values and these values can be modified using Subject.next([value here]).

Subjects are essentially Observables and you can subscribe to them to receive updates over time. Angular simplifies this process with the async pipe, handling subscriptions and disposal automatically when the component is destroyed.

While the "observable store pattern" presented here is basic, there are opportunities for further optimization. Remember to use Angular-specific syntax like (click) instead of traditional onclick, and avoid direct DOM manipulation in favor of data binding using brackets [].

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

Align the text to the right within a display flex container

Below is the code snippet: <div className="listContent"> <div> <div className="titleAndCounterBox"> <div className="headerListTitle">{list.name}</div><br /> <div ...

JavaScript: Launching the current page in a new tab or window

Is it feasible to open a new window or tab from the existing HTML page? Absolutely, I am referring to the current HTML page itself. Not triggered by an external call like this: window.open('page.html', '_blank'); Possible through Jav ...

"Trouble displaying specific events based on their IDs retrieved from the MySQL database

Each button in my list is associated with a specific person. Upon clicking a button, it directs to calendar.php?id=5 (where 5 is the personal id). I want the calendar to display the vacations scheduled for that particular id from the MySQL database. even ...

I cannot seem to alter the background color of my image through the use of external CSS

body { background-color: #f6f7d4; } h1, h3, hr { color: #68b8ab; } hr { width: 100px; border-style: dotted none none; border-color: gray; border-width: 5px; } img { background-color: black; } Although the external CSS code a ...

Tips on optimizing data processing for quicker display with ngFor

I am currently facing an issue with loading a JSON file containing 3500 data. The data appears very slowly on the view, causing the application to work sluggishly. Below is a snippet of the JSON: export class Service { private items = new Arr ...

Ways to showcase a div exclusively on UC mini browser

I'm looking for help to create a script that will only display a div with the class "info-box" in UC Mini browser. This div should be hidden in all other browsers. Can someone assist me with this? <!doctype html> <html> <head> <m ...

View real-time data in Vuejs 3 as it executes

I am currently working on a form that populates a table with data retrieved from a Laravel API. I am using Vue.js 3 and Composition API to build my entire application. When the button is clicked, I want the table to be filled with data from the form. The b ...

Exploring the functions of Safari input types: search, reset, and normalize

Is there a proper way to reset the appearance of a search input so that it resembles a text field in Safari? screenshot I'm experiencing an issue with Safari where there is unwanted padding on the left side of the search input that I can't seem ...

Is there a way to toggle or collapse a table row with a unique identifier using Angular and Bootstrap?

Currently handling Angular and Bootstrap in my work, but facing challenges with table manipulation and collapsing rows. I fetch data from a database and showcase it in a dynamically generated table using *ngFor and two rows within an ng-container. My goal ...

Running a designated AJAX function from a variable by utilizing Applescript

Struggling to execute a JavaScript code within a page using Applescript. In the JavaScript, an AJAX function was defined like so: var myFunction = function () { // Here be the code... } I attempted this in Applescript: do JavaScript "document.myFunct ...

import error causing an angular application to crash even with the module installed

Is there a possibility that an error is occurring with the import statement even though the syntax is correct and the required library has been installed? Could the issue lie within the core settings files, specifically the ones mentioned below (package.js ...

How to Modify Boolean Value in Angular 4 from a Different Component

Utilizing Booleans and a userRights.service to determine whether a navigation point should be displayed or hidden. The goal is to verify the user's rights upon login and then set the corresponding variables for navigation to either true or false. Thi ...

Display a loading indicator when loading a lazy loaded module in Angular 2

Here's my situation: I have a menu with various options that should be displayed based on user permissions. The majority of the menu items are contained within modules, and these modules are lazy loaded. This means that when a user clicks on a menu it ...

Synchronization problem encountered in an Angular app involving playwright

Currently, I am working on automating a process where the service queries the database and displays the data on the user interface. However, the rendering takes a considerable amount of time, around 3 minutes. Despite using Playwright for automation, it do ...

Element with negative z-index overlapping background of parent element

I am currently working on creating a CSS3 animated menu, but I am facing an issue where elements with low z-index values are displaying on top of their containing elements. This is causing the "sliding out" effect to be ruined. Here is the HTML: <html ...

Sending a div class as a parameter to a JavaScript function

Wondering if it's possible to pass a div's class into a JavaScript function. I'm using SquareSpace so adding an id to the div is not an option, but it works fine with divs that have ids. JQuery is already loaded. This is my current train of ...

Bespoke Video Player using HTML5 with "Nerdy Stats" Feature

I have been given the task of creating a streaming video testing framework for internal metrics and measurement purposes. Essentially, I am looking to develop an HTML5 player that can handle streams and provide performance data related to: - Average Bitr ...

Try out various scenarios using propsdata within Vue.js

In my component, there's a button that is displayed only when an article.link prop is not empty. I need to write a test to verify if the button is rendered when article.link has a value and another test for when it is empty. a.btn.plutus_btn-primary. ...

Guide on creating a function in PHP that takes a string input and outputs it in JSON format

Here is an illustration of a data structure that specifies the color of different fruits: array( "red" => array("apple, strawberry"), "yellow" => array("lemon", "ripe mango") ) Create a function called getFruits, which takes a color as input ...

Button component in React JS fails to appear on iPhones

After building a website using reactjs, I encountered an issue where the landing page's begin button is not displaying correctly on iPhones. The website works fine on all other devices, but on iPhones, the button is barely visible - with only a faint ...