Toggle button based on json response in angular 2 - json

I am trying to toggle button based on backend response.If the response is Yes, toggle button should be ON, if the response is No, toggle button should be off.
Below is my html code
<div class="btn-group btn-toggle">
<button class="btn btn-sm btn-default">ON</button>
<button class="btn btn-sm btn-primary ">OFF</button>
</div>
Below is my component code, where i calling a get service which returns response either Yes or No.I am calling the service in ngOnit() because i want to check whether the response is Yes /No when the page loads.Upon research i came to know we can achieve this using ngclass, but i am not sure how to do that.
ngOnInit() {
this.service.getFlagStatus().toPromise().then((flagStatus => {
this.flagStatus= flagStatus;
//if(flagStatus == 'Yes'){
//toggle right
// }else if (flagStatus == 'No') {
//toggle left
// }
}));
}
flagStatus variable has the response(Yes/No).
Let me know if i am doing in the right way.

Set right text in the component's code:
ngOnInit() {
this.service.getFlagStatus().toPromise().then((flagStatus => {
if(flagStatus == 'Yes'){
this.text = 'ON';
} else if (flagStatus == 'No') {
this.text = 'OFF';
}
}));
}
And pass it into the component's template (Angular/Interpolation):
<div class="btn-group btn-toggle">
<button class="btn btn-sm btn-primary">{{text}}</button>
</div>
Also you may play with classes (Angular/Class binding):
<button
class="btn btn-sm"
[class.btn-default]="text == 'ON'"
[class.btn-primary]="text != 'ON'">{{text}}</button>

Related

How to make each of these buttons when triggered, to make a different sound?

<div className="wrap">
<div id="tiles" className="columns">
<div id="ti">
<button id ="Q" className='drum-pad'>Q</button>
<button className='drum-pad'>W</button>
<button className='drum-pad'>A</button>
<button className='drum-pad'>S</button>
<button className='drum-pad'>D</button>
<button className='drum-pad'>S</button>
<button className='drum-pad'>Z</button>
<button className='drum-pad'>X</button>
<button className='drum-pad'>C</button>
</div>
</div>
...
Hello I am using React, I would like to trigger certain sounds when one of the buttons is clicked (example: Q is pushed, it trigger a piano sound) but nothing of what I did seems to work can you help me please?
You need a couple of things.
Add some audio tags to your html.
Setup click handler(s) for your buttons.
Pass the element of the clicked button to match the sound to the button. Here I'm using the attribute of the button to match up with the required sound. data-sound.
const playDrum = function(elem) {
const sound = (elem.getAttribute("data-sound"));
const audioElement = document.querySelector(`audio[data-sound="${sound}"]`);
audioElement.currentTime = 0;
audioElement.play();
}
Array.from(document.getElementsByClassName("drum")).forEach(
function(element, index, array) {
element.onclick = function() {
playDrum(element)
};
}
);
<button class="drum" data-sound="Q">Q</button>
<button class="drum" data-sound="W">W</button>
<audio data-sound="Q" src="https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/tom-mid.wav"></audio>
<audio data-sound="W" src="https://raw.githubusercontent.com/ArunMichaelDsouza/javascript-30-course/master/src/01-javascript-drum-kit/sounds/hihat-close.wav"></audio>

components interaction 2 way angular

I have 2 components - one for a list of items and one for several buttons like save,cancel,summary etc.
In my buttons component I am using inputs and outputs to call the methods I need.
<button type="button" class="btn btn-danger ml-3" (click)="submit(true)" *ngIf="allowUserToFinalize(false)">
Submit
</button>
<button type="button" class="btn btn-danger ml-3" (click)="submit(false)" *ngIf="allowUserToFinalize(true)">
Cancel
</button>
allowUserToFinalize(false) -> this method is on items component and I have to send a parameter to it and use the returned value.
I have tried to do that with Output and Input - I emit an event with the param value to the item component, call the allowUserToFinalize(param) and then the result is send via Input to the button component and it is used in the ngIf directive.
This is working only on init, it sends event=undefined, it returns true and then it is not triggered anymore.
Is there another method to do this interaction?
items html
<app-items-action-buttons>
(allowUserToFinalize)="allowUserToFinalize($event)"
[allowUserToFinalize]="allowUserToFinalize()">
</app-items-action-buttons>
items ts
allowUserToFinalize(submit: boolean) {
if (submit) {
return false;
} else {
return true;
}
}
butons ts
#Output() allowUserToFinalizeEvent: EventEmitter<any> = new EventEmitter();
#Input() allowUserToFinalizeInput;
allowUserToFinalize(submit: boolea) {
this.allowMerchantToFinalizeDealEvent.emit(submit)
}
buttons html
<button type="button" class="btn btn-danger ml-3" (click)="submit(false)" *ngIf="allowUserToFinalizeInput">
Cancel
</button>
That is quite a complicated data flow. Lemme try to propose a simpler one:
<button type="button" class="btn btn-danger ml-3" (click)="submit(true)" *ngIf="showSubmit">
Submit
</button>
<button type="button" class="btn btn-danger ml-3" (click)="submit(false)" *ngIf="showCancel">
Cancel
</button>
<app-items-action-buttons>
[showSubmit]="allowUserToFinalize(true)"
(showCancel)="allowUserToFinalize(false)"
>
</app-items-action-buttons>
And if you still want to keep the data flow you wanted to use originally. This way you need to pass the callback (think of callback hell right away) as in input property:
#Input() allowUserToFinalizeInput: (isSubmit:bool) => bool;
and use it right the way you use it now. there is no event here and no need for #Output property

Add Data Dynamically to HTML Button in HTML page

I have this button, I need to add Pendo Data that is dynamically working based on which button we chose. Mostly this is making the Button unique. When I have a button that is not changing I add like this:
<button mat-button
 data-pendo="pendo-prospects-send-application"
class='round-button'
color='primary'
type='button'
.....>
</button>
But sometime I need to add this data to one button that is changing based on CSS class. I am not sure how check for that.
For example I need to add to a button when :
if [class.fa-pencil] then data-pendo "Something"
if [class.fa-plus] then data-pendo "Something else"
This is the button that changes base on class:
<button mat-button
class='round-button'
type='button'
[class.disabled-button]='GuidId'
color='primary'
(click)='onAssignLoanOfficer()'>
<i class='fal'
[class.fa-pencil]='GuidId'
[class.fa-plus]='!GuidId'></i>
</button>
How I can do that?
Based on your comments I think this is what you want to do:
<button
(click)="onAssignLoanOfficer()"
[class.disabled-button]="GuidId"
[attr.data-pendo]="GuidId ? 'pendo-edit-loan' : 'pendo-add-loan'"
class="round-button"
color="primary"
type="button">
<i [class.fa-pencil]="GuidId"
[class.fa-plus]="!GuidId"
class="fall">
</i>
</button>
ALTERNATIVE:
As a more sophisticated alternative (I really don't know how you intend to use what you're asking for), you can build a directive to add the attribute you want based on a map of class-to-pendo-data conversion information:
#Directive({
selector: '[addPendoData]'
})
export class AddPendoDataDirective implements AfterViewInit {
constructor(private _el: ElementRef, private _renderer: Renderer2) {}
ngAfterViewInit() {
const pendoData: string | null | undefined = this._getPendoValue();
if (!pendoData) { return;}
const $button: HTMLElement = this._el.nativeElement;
this._renderer.setAttribute($button, 'data-pendo', pendoData);
}
private _getPendoValue() {
const $child: HTMLElement = this._el.nativeElement;
if(!$child) { return null; }
const $i: HTMLElement = $child.querySelector('i');
if(!$i) { return null; }
const listOfClasses: string[] = $i.className.split(' ');
if (!(listOfClasses && listOfClasses.length)) { return null; }
for(const className of listOfClasses) {
if(PENDO_MAP[className]) { return PENDO_MAP[className]; }
}
return null;
}
}
const PENDO_MAP: { [className: string]: string } = {
'fa-pencil': 'pendo-edit-loan',
'fa-plus': 'pendo-add-loan'
// add other mappings here...
};
and you can use it like this:
<button
(click)="onAssignLoanOfficer()"
[class.disabled-button]="GuidId"
addPendoData
class="round-button"
color="primary"
type="button">
<i [class.fa-pencil]="GuidId"
[class.fa-plus]="!GuidId"
class="fall">
</i>
</button>
I've put together this stackblitz demo.
You could define a directive, as julianobrasil suggests.
I want to point a different way to achieve this using Angular templates.
Define two buttons, addition and edition, separately.
Put a default where you want to be rendered
<div class="action-button" *ngIf="GuidId">
<!-- Add button -->
<button mat-button
data-pendo="pendo-add-loan"
(click)="add(...)"
class="round-button"
color="primary">
<i class="fal fa-plus"></i>
</button>
</div>
Then, define a ng-template tag with the other button definition. A completely fresh new.
<ng-template #edit-button>
<div class="action-button">
<!-- Edit button -->
<button mat-button
(click)="edit(...)"
data-pendo="pendo-edit-loan"
class="round-button"
color="primary">
<i class="fal fa-pencil"></i>
</button>
</div>
</ng-template>
Finally, just change the *ngIf statement to render either an addition button or an edition one.
<div class="action-button" *ngIf="!GuidId else edit-button">
<!-- Add button here -->
</div>
This is a way that scales in order to keep components isolated. The buttons are not related anymore, so you can implement w/o having to condition every style, action, etc.
Hope it helps.

How to stop property binding to every element in Angular within *ngFor

In my html, I want to apply property binding to every element.
I have a click and hover event that I want to do whenever the user
hovers or clicks on an individual element. But right now the hover or
click happens to every element within the *ngFor. I want it to only
happen on the element they are selecting/hovering over. What do I need
to change?
I saw another stackoverflow answer and they simply applied the name
within the for loop (ex: *ngFor="let article of articles" and they
used article) in front of the boolean/variable they were setting.
Like my boolean is favorite so they did article.favorite within
the element and it apparently worked, but that method doesn't work for
me.
Code:
<div class="row">
<!--/span-->
<div class="col-6 col-sm-6 col-lg-4"
*ngFor="let article of articles">
<h2>{{article.title}}</h2>
<h4>By: {{article.author}}</h4>
<p>{{article.body}}</p>
<div class="col-lg-4">
<button type="button" class="btn btn-default" (click)="addFavorite()"
(mouseenter)="hoverFavorite()"
(mouseleave)="removeHoverFavorite()">
<span
class="glyphicon"
[class.glyphicon-heart]="favorite"
[class.glyphicon-heart-empty]="!favorite"
aria-hidden="true"></span> Favorite
</button>
</div>
<div class="col-lg-4">
<button type="button" class="btn btn-default">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Comment
</button>
</div>
<div class="col-lg-4">
<button type="button" class="btn btn-info pull-left" [routerLink]="['/articles', article.articleId]">Read More »
</button>
</div>
</div>
</div>
<!--/row-->
Adding component
import { Component, OnInit } from '#angular/core';
import {ArticlesService} from "./articles.service";
import {Article} from "./article.model";
import {Router} from "#angular/router";
#Component({
selector: 'app-articles',
templateUrl: './articles.component.html',
styleUrls: ['./articles.component.css']
})
export class ArticlesComponent implements OnInit {
articles: Article[];
// if favorite = false then full heart is not shown. if true then heart shown
favorite: boolean = false;
// clicked will be used to determine if we should keep hovering effect on
clicked: boolean = false;
constructor(private router: Router, private articleService: ArticlesService) { }
ngOnInit() {
this.articleService.getArticles()
.subscribe(
(articles: Article[]) => {
this.articles = articles;
}
);
}
addFavorite(){
// toggle full and empty heart
this.clicked = !this.clicked;
if (this.clicked === true){
// if clicked then add to database and show full heart
this.favorite = true;
} else { // if false then remove from database and show empty heart
this.favorite = false;
}
}
hoverFavorite(){
// if clicked is false then show hover effect, else dont
if (this.clicked === false){
this.favorite = true;
}
}
removeHoverFavorite(){
// if clicked is false then show hover effect, else dont
if (this.clicked === false){
this.favorite = this.favorite = false;
}
}
}
You can use the index
*ngFor="let article of articles; let i=index"
(click)="addFavorite(i)"
// or
(click)="addFavorite(article)"
(mouseenter)="hoverFavorite = i"
(mouseleave)="hoverFavorite = -1"
[class.glyphicon-heart]="favorite === i"
[class.glyphicon-heart-empty]="favorite !== i"
The reason you're not getting the desired result is because defined your boolean variables in the ArticlesComponent, which is the component rendering the list of articles. Thus, if the variables become true, it would be true for all the articles, instead of a single one. To fix it you should define all of the content within the ngFor loop as its own component, and in that component you would set those boolean variables. That way, each instance of an ArticleComponent would have its own variables and they wouldn't interfere with each other.

How to use ng-show and ng-hide with buttons in AngularJS

I have two buttons Start and Stop,when I click the Start button I want the Stop button to show and the Start button to be hidden vice versa when I click the Stop button I want the Start button to be shown and the Stop button to be hidden.Only one button must be shown at any one time.Here is what I tried but it doesn't seem to work.Where am I going wrong?
<span ng-hide="Model.StartEvent == true">
<button ng-click="Model.StartEvent()" id="btnEventStart">Start</button>
</span>
<span ng-show="Model.StopEvent == false">
<button ng-click="Model.StopEvent()" id="btnStopEvent" class="tooltip">Stop</button>
</span>
You could do even less
<button ng-click="goEvent();" ng-hide="going">Start</button>
<button ng-click="goEvent();" ng-show="going">Stop</button>
...
$scope.going = false;
$scope.goEvent = function(){
$scope.going = !$scope.going;
if($scope.going){
$scope.go();
}else{
$scope.stop();
}
}
you should use same variable for both...
<button ng-click="Model.toggleShow(); Model.StartEvent()" ng-show="Model.showStartEvent">Start</button>
<button ng-click="Model.toggleShow(); Model.StopEvent()" ng-show="!Model.showStartEvent">Stop</button>
Modal.toggleShow = function(){
Model.showStartEvent = !Model.showStartEvent;
}
also you can call toggle right inside the startevent/stopevent rather than having two function calls on ng-click
Html:
<div ng-controller="YourController">
<span ng-hide="EventRunning"><button ng-click="StartEvent($event)"id="btnEventStart">Start</button></span>
<span ng-show="EventRunning"><button ng-click="StopEvent($event)" id="btnStopEvent">Stop</button></span>
</div>
Use single semaphore for hide and show EventRunning
Controller:
{ ...
$scope.EventRunning = false;
$scope.StartEvent = function (event) {
event.preventDefault();
$scope.EventRunning = true;
// your code
}
$scope.StopEvent = function (event) {
event.preventDefault();
$scope.EventRunning = false;
// your code
}
... }