Change color of popup (angular, TS) - html

I build a custom popup which is visible when I click a button. When I click somewhere else on the document the popup should be closed / invisible.
That works pretty well.
Now I want to change the style property of this popup. The problem is that i cant change it.
The code below returns that the HTML object is null but if i click another buttom with same functionality the style changes.
Thats my code so far
tooltip.component.ts
export class TooltipComponent implements OnInit {
popup = false;
// open popup
openToolTip($event: {
target: any; stopPropagation: () => void;
})
{
$event.stopPropagation();
this.popup = !this.popup;
testvariable = document.getElementByID("popupId");
testvariable.style.backgroundcolor = "green"; //backgroundcolor just for testing
}
}
// close popup if clicked on document
#HostListener('document:click', ['$event']) onDocumentClick(event: any) {
this.popup = false;
}
constructor() { }
ngOnInit(): void {
}
}
html
<span class="info-icon" (click)="openToolTip($event)">
<mat-icon>info_outline</mat-icon>
</span>
<div *ngIf="popup" id="popupId" class="popup" (click)="$event.stopPropagation()">
<div class="text-box">
</div>
<!-- close-button -->
<a class="close" (click)="popup = false">×</a>
</div>```
EDIT:
I used the timeout function like Elikill58 said. Its a workaround but it solves my problem for now :)

The problem comes from the element isn't known yet. You are checking it too fast. There is multiple way to fix it:
Wait for it.
You can use the timeout function:
timeout(function() {
var testvariable = document.getElementByID("popupId");
testvariable.style.backgroundcolor = "green";
}, 0);
Set style with ngStyle.
If the style should depend of values, you can do like:
<div [ngStyle]="{'background-color': something ? 'green' : 'red'}">
</div>
Change style by default.
This will change the style for all popup, without requiring JS manipulation:
.popup {
background-color: green;
}
Change style with ID.
If you are using specific ID, you can do like:
#popupId {
background-color: green;
}
All ways have advantages and disadvantages, you should take the one that correspond to what you are looking for.

Related

(Angular) Clicking on a button highlights another button because I'm changing a value in an array. Why?

So I'm trying to make a website using Angular and have come across a very peculiar bug.
Basically I have an *ngFor div that creates 12 buttons.
<div *ngFor = "let color of colors; let i = index" style = "display: inline;">
<button (click) = "toggleTrue(i)" id = "{{i}}" class = "coloredButton">
</button>
</div>
When a button is clicked then it should highlight the button and then change a value in an array within my component like so.
toggleTrue(id: number){
this.colors[id] = !this.colors[id];
var button = document.getElementById(id.toString());
if(this.colors[id] === true){
button.style.border = "10px";
button.style.borderColor = "white";
button.style.borderStyle = "solid";
}
else{
button.style.borderStyle = "none";
}
}
However for some reason whenever I click a button it highlights the button next to it and if I click it twice more than it will highlight a button two buttons away for some reason, click it twice more and it'll highlight a button three buttons away, etc. It's not highlighting the right button, but the id it passes through to the function is correct, I checked using console.log(id).
I've messed around a bit (taking out classes and lines and whatnot) and I've isolated the problem to this line.
this.colors[id] = !this.colors[id];
If I remove this then everything works fine (except of course I can't edit the value of the array anymore). This is proven further when I remove the click function of my buttons and the default highlight for buttons correctly highlights the right button.
Can anyone please help me out and tell me why it's not highlighting correctly? Any help would be appreciated.
If you're curious I created the array earlier within the component using colors = [] and it's an array of booleans that I filled within the constructor using a basic for loop.
https://codesandbox.io/s/crimson-brook-wn3q0?file=/src/app/app.component.html
Here is a sandbox with a solution.
Essentially you want to keep styling in the template through the use of NgClass or NgStyle
and use the component just for changing state, avoid accessing the DOM directly due to lifecycle problems.
Typescript
export class AppComponent {
colors: boolean[];
constructor() {
this.colors = [];
for (let i = 0; i < 10; i++) {
this.colors.push(false);
}
}
toggleTrue(id: number) {
this.colors[id] = !this.colors[id];
}
}
HTML
<div>
<div *ngFor="let color of colors; index as i">
<button
(click)="toggleTrue($event, i)"
id="{{i}}"
[ngClass]="{'active':colors[i]==true}"
>
button
</button>
</div>
</div>
CSS
.active {
color: red;
}
.inactive {
color: blue;
}
You could do some changes in your code. Firs in your HTML:
<button *ngFor="let color of colors; let i = index" (click) = "toggleTrue(i)" class = "coloredButton" [class.active]="color"> {{i}} < /button>
You noticed about [class.active]="color" this sentence verify if color is true the button will have the active class
.active {
border: 10px solid white;
}
I don't know how you generate colors array but I assumed somethings and also change your function in the class component
colors = new Array(10).fill(false);
toggleTrue(index: number) {
this.colors[index] = !this.colors[index]
}

How to highlight a div or make a div active when clicked

i have several divs and if a div is clicked, i want to hightlight the div by changing the background-color of the div as well as the text in the div(i.e. make it active). I have done this before using JQuery by defining a class in my css and dynamically removing and adding the class. How can this be accomplished in Angular2. From researching and i shouldn't be manipulating the DOM as this is a no no in angular2. I have looked online for several examples but no success. Please
One way is to make an attribute directive. Fortunately for you, Angular has a guide for doing almost exactly what you are looking for but with hover events. To respond to clicks instead, for the 'Respond to user action' section...
... replace this:
#HostListener('mouseenter') onMouseEnter() {
/* . . . */
}
#HostListener('mouseleave') onMouseLeave() {
/* . . . */
}
with this:
#HostListener('click') onMouseClick() {
/* . . . */
}
To acheive a result where clicking a div that is already highlighted will unhighlight it, the full directive code would be:
import { Directive, ElementRef, HostListener, Input } from '#angular/core';
#Directive({
selector: '[myHighlight]'
})
export class HighlightDirective {
private _defaultColor = 'red';
private el: HTMLElement;
private highlighted: boolean = false;
constructor(el: ElementRef) { this.el = el.nativeElement; }
#Input('myHighlight') highlightColor: string;
#HostListener('click') onMouseClick() {
this.highlighted ? this.highlight('') : this.highlight(this.highlightColor || this._defaultColor);
}
private highlight(color: string) {
this.el.style.backgroundColor = color;
}
}
To use the directive, you apply it to an element like so:
<!-- With default color -->
<div [myHighlight]>Click to highlight me!</div>
<!-- With custom color -->
<div [myHighlight]="yellow">I'm a div, la di da.</div>
Just set a property depending on what item was clicked and set a class if the value matches the one of the current item. Use CSS to apply styles:
#Component({
styles: [`
div.highlight {
background-color: red;
}`
],
template: `
<div (click)="highlighted = 1" [class.highlight]="highlighted === 1">div1</div>
<div (click)="highlighted = 2" [class.highlight]="highlighted === 2">div2</div>
<div (click)="highlighted = 3" [class.highlight]="highlighted === 3">div3</div>
`
})
class MyComponent {
hightlighted:number = 0;
}

Ng-class - Active / Inactive button

I have a button range with 2 buttons, and I want, when user click on one of them, ng-class add class on button active (My two views are displayed by ng-show/hide).
I have test this, but it's don't work :
HTML :
<div class="button-bar">
<a class="button btn-transpr-left" ng-class="{'activ-btn': isActive1}" ng-click="firstStep()">Acceptées</a>
<a class="button btn-transpr-right" ng-class="{'activ-btn': isActive2}" ng-click="nextStep()">En attente</a>
</div>
CSS :
.activ-btn {
border-bottom: 3px solid !important;
font-weight: bolder !important;
}
JS :
$scope.isActive2 = false;
$scope.isActive1 = true;
$scope.nextStep = function() {
$scope.data.step += 1;
$scope.isActive1 = $scope.isActive1;
$scope.isActive2 = !$scope.isActive2;
}
$scope.firstStep = function() {
$scope.data.step = 1;
$scope.isActive1 = !$scope.isActive1;
$scope.isActive2 = $scope.isActive2;
}
Maybe I make mistake ... Someone can help me ?
Thank's all folk !
Part of the issue was that you weren't defining data on your scope. It was undefined and error-ing out.
$scope.data = { step: 1 }
I've simplified this for you. You don't need to really drive this by explicit flags on your scope, rather you can simply do a check to see if the current step value is what you want on the button in the ng-class expression
ng-class="{'activ-btn':data.step == <desired step value>}"
test - http://codepen.io/jusopi/pen/EPyONL

Disable a div in AngularJS with ng-click property?

I need to disable a div in AngularJS depend on a condition. Yes I can do it by using css change (giving low contrast and less color appearance) in appearance but I have ng-click property in it. So I need to prevent that calling also. How can I do it?
Here is my code:
<div ng-repeat="item in list.items" ng-click="goToFunction()" ng-disabled="true">
Yes ng-disabled does not work for div. It will for each html element which support the disable property (eg : input).
https://docs.angularjs.org/api/ng/directive/ngDisabled
I created a simple fiddle to demonstrate how to achieve it with a simple div http://jsfiddle.net/5Qc5k/1/
function MyCtrl($scope, $templateCache) {
$scope.isDisabled = false;
$scope.alertMe = function(){
if($scope.isDisabled === true){
return;
}
// disable the function
$scope.isDisabled = true;
alert("foo");
}
}
You can do that in controller ie:
<div ng-repeat="item in list.items" ng-click="goToFunction(item)" ng-disabled="true">
and after that in controller:
function goToFunction(item){
if(item.condition == disable){
return false
}
else {
// do something
}
}
To prevent the ng-click functionality based on disable you can do in following:-
<div ng-repeat="item in list.items" ng-disabled="item.condition" ng-click="goToFunction(item)">
item.value
</div>
$scope.goToFunction = function(item){
if(item.condition == false){
// Dont do anything
}else{
//do something
}
In this scenario when div is disabled, click functionality wont do anything, otherwise it will do.

knockoutjs css binding value when boolean computed property is false/true

I am binding my currently selected item like this:
The selected item gets visible, but how can I give the unselected items an unselected/default background color? When I set a background color to the template class I do not see anymore the background color set from the selection via mouse click.
Is the problem maybe that I have 2 backgrounds set but none is removed?
<div data-bind="foreach: items">
<div class="cellContainer" >
<div class="template" data-bind="click: $parent.selectItem, css: { selected: isSelected }">
<div data-bind="text: number"></div>
</div>
</div>
</div>
.selected {
background-color: #0094ff;
}
Sounds like a cascade issue. Make sure your ".template" style is defined before your ".selected" style in your css file.
Make sure your selectItem method resets isSelected on all elements before setting it to true on the argument. A naive implementation could be:
var ViewModel = function() {
// Skipped the rest for brevity...
self.selectItem = function(item) {
// Deselect all items first
for (var i = 0; i < self.items().length; i++) {
self.items()[i].isSelected(false);
}
// Select the argument
item.isSelected(true);
};
};
See this jsfiddle for a demo.
However, it is often easier to keep a reference on the parent view model to the currently selected item, and change the css binding to something like:
css: { selected: $parent.TheOneSelectedItem().number() == number() }
See this fiddle for the alternate demo.
Something like this might work.
.template {
background-color: #fff;
}
.template.selected {
background-color: #0094ff;
}
It does not look like a knockout issue.