Add CSS if host has (click) - html

I'm building a library and I have a <my-card> component. It's a component that will often have a (click) handler on it.
What I'm looking to do is to add cursor: pointer automatically when the component has (click) attached to it.
So for example, <my-card> would have the default cursor, and <my-card (click)="onClick()> would apply cursor: pointer to the component element.
Any clean way of doing this?

If you're able to change (click) to click then you could do this using CSS.
HTML:
<my-card>Look at me</my-card>
<my-card click="onClick()">Click me</my-card>
CSS:
my-card {
border-radius: 3px;
display: inline-block;
padding: 5px;
}
[click] {
background-color: red;
color: white;
cursor: pointer;
}
The [click] part in the CSS references an attribute of an element. So, this will target any element you use with the click attribute. If you only want to target any <my-card> element with the click attribute then you would change your CSS to my-card[click].
Here's a fiddle for you to reference: https://jsfiddle.net/8w9Lqxr4/1/

The Angular way to do this is to use a directive, take a look at this example:
import { HostBinding, Directive } from '#angular/core'
#Directive({
selector: '[myClick]'
})
class MyClickDirective {
#HostBinding('class.mousepointer') private isClick: boolean;
constructor(private el: ElementRef,
private renderer: Renderer) {
}
#HostListener('click') onMyElemClicked() {
this.isClick =!this.isClick;
}
}
I've not tested this example but this is the way you must investigate.

Related

How to change style of a child angular component to be same size as another child component

I have been struggling with this for a quite some time now, and i couldn't find a sufficient answer. Basically i have one parent component which html goes as follows:
<div class="container">
<child-one></child-one>
<child-two></child-two>
</div>
the problem is that the child-one component has its size set as auto, with some padding to look good,
child-one {
width: auto;
height: auto;
padding: 0.5rem;
}
and child-two has a fixed width and height in it's own scss.
child-two {
width: 10rem;
height: auto;
}
is there a way to somehow change the width of child-two in the parent without editing the child-two?
I was hoping for something along the lines of storing the width of the child-one, and setting the width of child-two to the same value.
child-one {
width:auto;
padding: 0.5rem;
$width: this.width !global //idk about this one
}
child-two {
width: $width
padding: 0.5rem
}
please note that the child-one and child-two scss don't look this way in the code, and are normally written, this is just for the purpose of simplifying the question
Is this what you are looking for?
app.component.html - Parent Component
<child-one #childOne></child-one>
<child-two #childTwo></child-two>
<br>
<button (click)="changeWidth()">Change child two width</button>
app.component.ts
export class AppComponent {
#ViewChild('childOne', {
read: ElementRef
}) childOne: ElementRef;
#ViewChild('childTwo', {
read: ElementRef
}) childTwo: ElementRef;
constructor(private renderer: Renderer2) {}
changeWidth() {
const childOneWidth = this.childOne.nativeElement.getElementsByClassName('child-one')[0].offsetWidth;
const childTwoElement = this.childTwo.nativeElement.getElementsByClassName('child-two')[0];
this.renderer.setStyle(childTwoElement, 'width', `${childOneWidth - 2}px`);
}
}
Here is the working Stackblitz
Suggestion
#SivakumarTadisetti's suggestion is a valid suggestion, alternatively, you could use ngStyle to provide dynamic styling for the component or ngClass for conditionally applying style class to the component. You could, which requires more code, also write a directive that changes the style behaviour of the component based on certain conditions.
Example using ngStyle
https://stackblitz.com/edit/stack-help-01

Change font size for ion-searchbar input in Ionic 5

How do I change the font size of ion-searchbar input? Could anyone please help.
<ion-searchbar></ion-searchbar>
Here's what I tried but this does not work
.searchbar-input {
font-size: 10px;
}
Please refer to the working example which I created in Stackblitz
In Ionic 5
global.scss
ion-searchbar {
.searchbar-input-container {
input{
font-size: 14px !important;
}
}
}
Why do you have <style> tag within your home template file? Angular (what Ionic has underneath) template compiler doesn't allow it and will remove any <style> tag you add.
If you have a global .css or .scss file (e.g. index.scss) than you can simply put your .searchbar-input style there, and it should work.
Another way I can think of is, adding encapsulation: ViewEncapsulation.None to your HomePage component, which would be not ideal or could break some things, but still should work.
Check the demo: https://stackblitz.com/edit/ionic-ionsearchbar-styling-vda1eu
What I mean is this:
home.ts
#Component({
selector: 'page-home',
templateUrl: 'home.html',
styleUrls: ['./home.scss'], // added
encapsulation: ViewEncapsulation.None // added
})
export class HomePage { /*... */ }
home.scss
.searchbar-input {
font-size: 10px !important;
}
This my solution in Ionic 5:
Global.css
.searchbarinput {
input{
font-size: 20px !important;
}
}
In search page:
<ion-searchbar #searchbar (ionInput)="getProdForSearch($event)" class="searchbarinput" placeholder="Buscar produtos..." search-icon="search-sharp"></ion-searchbar>

Change the icon for mat-radio-button

How could I change the mat-radio-button to check-mark and cross-mark looks like following?
Thank you!
My code is here:
<mat-radio-group class="radio" (change)="onChange($event)"
name="exemplars">
<mat-radio-button class="radio-custom" [value]="true" [checked]="function()"> Accept </mat-radio-button>
<mat-radio-button class="radio-custom" [value]="false" [checked]="function()"> Reject</mat-radio-button>
</mat-radio-group>
icons I want to use :
Don't think this is the most elegant solution but it does the job.
In my case I'm using Angular 10 (2+) with all the ::ng-deep stuff so align the code for your needs.
I'm using an icomoon font with the icons my company is using so take this into consideration when applying this solution.
In my app.component. styling file:
::ng-deep {
.mat-radio-button {
.mat-radio-container {
.mat-radio-outer-circle:before {
font-family: "icomoon" !important; // here comes the icomoon font reference that defines the actual icon to be shown
content: "\e901"; // the code of the icon from my iconfont => change this one to the X icon of yours
position: absolute; // this and next 3 lines are for centering the icon in the circle of the radio button
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.mat-radio-inner-circle {
/* feel free to design the actual inner radiobutton circle as you wish*/
}
}
.mat-radio-button .mat-radio-checked {
.mat-radio-container {
.mat-radio-outer-circle:before {
content: "\e900"; // the code of the icon from my iconfont => change this one to V icon of yours
}
}
}
}
}
Feel free to enhance the code with all other stuff: sizes, borders, coloring, etc.
Create a new directive that binds to mat-radio-button or any other selector you need, e.g. mat-radio-button.radio-custom
Inject ElementRef into the directive's constructor
Use the instance of ElementRef to find .mat-radio-inner-circle
Set the innerHTML of the found html element to the svg of your desired icon.
Example:
#Directive({
selector: 'mat-radio-button',
})
export class CustomRadioButton implements OnInit {
constructor(private elementRef: ElementRef) {}
ngOnInit() {
this.appendIcon();
}
appendIcon() {
const innerCircle = this.elementRef.nativeElement.querySelector('.mat-radio-inner-circle');
innerCircle.innerHTML = YOUR_SVG_CODE;
}
}

How to style Angular Material select drop down overlay

I have an angular component called currency-selector which has its own css file that looks like this:
.currency-select {
position: absolute;
top: 5px;
right: 80px;
z-index: 1000000;
color: #DD642A;
font-size: 17px;
padding-right: 16px;
width: 130px;
}
.mat-form-field {
display: block;
}
This works exactly as expected for the selector until it is clicked and the drop down happens. The html is as follows:
<div class="currency-select">
<mat-form-field *ngIf=loaded>
<mat-select [formControl]="currencyForm" placeholder="Select Currency">
<select-search (search)="filterCurrencyOptions($event)" #selectSearch (keydown)="$event.stopPropagation()" >
</select-search>
<mat-option *ngFor="let currency of filteredCurrencies" [value]="currency.counter_currency_code" (click)="updateCurrency()">
<flag-icon country="{{ (currency.counter_currency_iso_2 || '').toLowerCase() }}"></flag-icon> {{currency.counter_currency_code}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
When I click on the currency select, the drop down doesn't appear how I want it to appear and I can't seem to add anything in the currency-select.component.html file to alter it, instead it seems to take the styling from a different div tag, "cdk-overlay-container".
Can anyone advise as to how I can write the css for this in the currency-select css file? I've tried using !important but this isn't working eithher.
To style the drop down overlay add a class to it using the mat-select input panelClass.
<mat-select panelClass="myPanel">
Then use ::ng-deep:
::ng-deep .myPanel.mat-select-panel {
background-color: darkslategray;
}
Or disable ViewEncapsulation for the component:
#Component({
selector: 'select-panel-class-example',
templateUrl: 'select-panel-class-example.html',
styleUrls: ['select-panel-class-example.css'],
encapsulation: ViewEncapsulation.None,
})
.myPanel.mat-select-panel {
background-color: darkslategray;
}
https://stackblitz.com/edit/angular-k4pxc1
try using ng-deep
::ng-deep .your-class-name {
...
}
PS: ng-deep will get deprecated in further versions. W3C didn't defined a 'replacement' for it yet.
Answer Update (07-07-2021): If you don't want to use ng-deep (deprecated), then use ViewEncapsulation.None: angular.io/guide/component-styles#deprecated-deep--and-ng-deep

Hover a div with NgClass

I am trying to make a hover effect on a div with a Angular ngClass directive. In the template file I have a div element with class "list-item-container' which contains a div with class "list-item" that is iterated with a *ngFor directive. Inside the "list-item" div element I have three divs with class "list-item-column" which are placed horizontally like a table row with inline display. in the div with "list-item" class I have placed a mouseenter and mouseleave event listeners which calls hoverListItem() in my .ts file. the hoverListItem() function changes the value of listItemHovered variable to true or false. In the "list-item" class I have a ngClass directive which triggers a css class 'list-item-highlight' based on the value of listItemHovered boolean value which then changes to background to a different color.
The problem I'm facing is that upon hovering mouse pointer on the "list-item" div all my "list-item" divs are affected instead of the one I am hovering over. How to solve this problem?
.html file
<div class="list-item-container">
<ng-container *ngFor="let opportunity of dealService.opportunities">
<div [ngClass]="{'list-item-highlight': listItemHovered}" class="list-item" (mouseenter)="hoverListItem()"
(mouseleave)="hoverListItem()"
(click)="selectOpportunity(opportunity)">
<div
class="list-item-column">{{opportunity.account?.name === null ? "N/A" : opportunity.account.name}}</div>
<div class="list-item-column">{{opportunity.requirementTitle}}</div>
<div class="list-item-column">{{opportunity.salesValue | number: '1.0-2'}}</div>
</div>
</ng-container>
</div>
.css file
.list-item-container{
overflow: auto;
width: 100%;
max-height: 500px;
}
.list-item{
font-size: 15px;
border-radius: 10px ;
margin-top: 5px;
height: 50px;
background: lightgray;
color: black;
}
.list-item-highlight{
background: #7e00cc;
color: white;
}
.list-item-column{
height: inherit;
vertical-align: center;
display: inline-block;
width: 33.33%;
padding-left: 40px;
}
.ts file
hoverListItem() {
this.listItemHovered = !this.listItemHovered;
}
Right now you're creating and modifying listItemHovered flag inside component context, rather you should maintain a flag for each item level, which could help to easily identify wheather component has been highlighted or not.
[ngClass]="{'list-item-highlight': opportunity.listItemHovered}"
(mouseenter)="hoverListItem(opportunity)"
(mouseleave)="hoverListItem(opportunity)"
Component
hoverListItem(opportunity) {
opportunity.listItemHovered = !opportunity.listItemHovered;
}
Though I'd recommend to use :hover pseudo class if requirement is just to highlight the element on hover. That can be easily doable by changing CSS rule. This way could save several change detection cycle to be ran.
.list-item:hover {
background: #7e00cc;
color: white;
}
I would suggest use a directive to listen to the hover event on the target element and attach the class:
#Directive({
selector: '[hoverDir]'
})
export class HoverOverDirective {
#HostListener('mouseenter') onMouseEnter() {
this.elementRef.nativeElement.class = 'list-item-highlight';
}
#HostListener('mouseleave') onMouseLeave() {
this.elementRef.nativeElement.class = 'list-item-not-highlight';
}
}
Or the easiest way is to make use of CSS pseudo property :hover and use it as below:
.list-item:hover {
background: #7e00cc;
color: white;
}