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

Angular application unable to invoke the Web API GET method

Just starting out with Angular. I've got a WebAPI controller set up with a get method that returns data. Everything runs smoothly when I access it from the browser directly. But for some reason, when I try to call the same method from my Angular ap ...

Calculating the sum of values in a GridView using ASP.NET

I have an ASP.NET Web Application where I am utilizing a BulkEditGridView to create an order form. This GridView allows users to edit all rows simultaneously. Within the grid, there is a column that calculates the total cost for each item (cost x quantit ...

Is there a way to verify the phone number input field on my registration form along with the country code using geolocation

I'm currently working on a registration form that includes an input field for telephone number. I'd like to implement a feature where, upon filling out the form, the telephone input field automatically displays the country code by default. Would ...

Implement the maskmoney library in your input fields

In the form below, I am automatically adding inputs using a JavaScript function like this: $('.Preco1').maskMoney({ decimal: '.', thousands: ' ', precision: 2 }); $('.Preco1').focus(); $('#sub').maskMon ...

What is the most effective way to transmit multiple pieces of server-side data to JavaScript?

Imagine having multiple Javascript codes embedded in pages. Currently, it's simple to initialize variables by using Print/Echo statements to set JavaScript values. For example: var x = <?php echo('This is a value');?> Initially, I co ...

The JOI validation process is failing to return all error messages, even though the "abort early" option

I have been encountering an issue while trying to validate my payload using a joi schema. Instead of returning the errors specified in the schema, only one error is being displayed. Even when I provide a payload with name as "int", it only shows one custom ...

Is there a way to use a Google Chrome command line switch to simulate the dimensions of a

Seeking information on the available Google Chrome command line switches for emulating device sizes. Specifically, I need to test a component that utilizes CSS @media queries for min-device-width/min-device-height. Previous attempts with --window-size an ...

What are some methods for preventing JavaScript function calls from the browser console?

In the process of developing a web application using HTML and JavaScript, I'm looking for a way to prevent users from accessing functions through their browser console in order to maintain fairness and avoid cheating. The functions I want to protect a ...

Successful execution occurring prior to beforeSend in a Cordova iOS application utilizing jQuery Ajax

After making some changes to the HTML of the login button, I encountered an issue where the alert was being triggered before the button's HTML had updated when testing on my iPhone using a Cordova-built app. Strangely, this problem did not occur when ...

Do I have to divide the small functions in my Node.js controller into smaller ones?

When signing up users in my controller, do I need to break up the sign-up steps into individual asynchronous calls or is one big asynchronous call sufficient? Each step relies on the previous one: Validate user Create user Create group Add user to group ...

The technique for handling intricate calls in node.js

My goal is to create a social community where users are rewarded for receiving upvotes or shares on their answers. Additionally, I want to send notifications to users whenever their answers receive some interaction. The process flow is detailed in the com ...

Exploring the power of NestJS integration with Mongoose and GridFS

I am exploring the functionality of using mongoose with NestJs. Currently, I am leveraging the package @nestjs/mongoose as outlined in the informative documentation. So far, it has been functioning properly when working with standard models. However, my p ...

The external IP address cannot be accessed beyond the function scope in Node.js

Recently joining this community, I am in the process of retrieving my external IP through a package called "external-ip." The example code provided by them looks like this: const getIP = require('external-ip')(); getIP((err, ip) => { ...

Create node panels using GoJS and apply paint to them to enhance

Hey there! I'm looking to style my node similar to the one on the right using GOjs. Any suggestions on how I can achieve that? The left node is what I currently have, but I really want to paint it like the right node. It seems like some parts are mi ...

When attempting to pre-render a Next.js page using getStaticProps(), an error occurs stating that the image is missing the required "src" attribute when using next/image

After reading the documentation for nextjs, I learned that the getStaticProps function should pre-render data that I need before a user visits my site. My goal is to fetch images and load them onto cards. In my index.js file: export async function getSta ...

progressing both forward and backward through every month

I am currently working on a project that involves creating a calendar using JavaScript. I have implemented functionalities where I can navigate back and forth through months, fetching the days within each month. However, I am facing an issue where if I go ...

Encountering an error with [object%20Object] when utilizing ajaxFileUpload

I wrote a JavaSscript script that looks like this: $.ajaxFileUpload({ url: url, secureuri: false, fileElementId: ['upload-file'], dataType: "JSON", data:{ "sample_path":$(".demo-view-container-left .vie ...

Setting up proxy middleware in an express application

My application is structured with a frontend server (React) serving static files and a backend server (Express). I have noticed that custom header requests trigger preflight requests, causing latency in my application. My goal is to eliminate these preflig ...

Creating resizable SVG elements using HTML or CSS for dynamic width and height

Is there a way to give my SVG element dynamic width and height in order to display the entire SVG image? For example, take a look at this CodePen link. <svg width="250" height="250" viewBox="0 0 250 250"> Alternatively, .svg { width : 250px; ...

Attempting to start an Angular project using NG NEW constantly fails nowadays - always ends with error code EPERM

Can Angular still be considered a reliable framework when pervasive errors and bugs persist for extended periods without any clear resolution documented? .... 24695 silly saveTree | +-- <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cf ...