Change the icon for mat-radio-button - html

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;
}
}

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

Angular Css not being executed from angular component css

My angular project is reading from a library that contains this code is a class:
class MyClass extends EventEmitter {
constructor () {
// add the element to the container
this.loadingElement = document.createElement('div');
this.loadingElement.className = "loading"
this.loadingElement.innerText = 'Now Loading...';
}
}
In my app.component.css I have this:
#componentDivId .loading {
position: absolute;
top: 50%;
left: 50%;
}
This css is in app.component.css
How can I change this so it reads the css?
You should look into ::ng-deep for overriding component styling. Also, may need to use !important in css file as and when required
Here is a demo code to help you understand how ::ng-deep can be used to push styling to a child component.

Add CSS if host has (click)

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.

Angular component opacity does not work anymore when using Bootstrap

In my Angular application, I have two components, A and B, the first is a toggle button and the second is a form. B component subscribes to the state of the A component using a service in order to set its CSS according to the observed toggle state. For example, if the A component is set to state 'leftPressed', the component B reacts to this state setting its own CSS to 'enable' (through [ngStyle]) in order to make the form usable by the user, instead if the A component is set to the state 'rightPressed' the B component sets its own CSS to 'disable'. This is the code of the CSS disable style:
.disable {
opacity: 30%;
pointer-events: none;
}
This strategy will opacize the form and make the same form not clickable by the user.
My problem is that this thing worked until I introduced in my project Bootstrap in order to make my application more responsive (I have just placed these two buttons in the div-row-col scheme according to the Bootstrap modus operandi), but the strange thing is that only the opacity does not work on the B component but the 'mouse-event: none' worked as expected.
How can it be possibile that a CSS, in that case, is valued partially? The only thing I know is that if I roll back putting those components in my previous HTML without Bootstrap code, everything works fine.
Update with more code:
This is the code of my HTML component in which is declared more components
<!--This is the bar without Bootstrap that works-->
<div class="searchBar">
<app-button-search-city-polygon-component></app-button-search-city-polygon-component>
<app-search-city-bar [ngClass]="[cityBarStyle]"></app-search-city-bar>
<app-clear-polygon-bar [ngClass]="[polygonBarStyle]"></app-clear-polygon-bar>
<app-button-search-centers-or-operators></app-button-search-centers-or-operators>
<app-validate-and-search-button></app-validate-and-search-button>
</div>
<!--This is the bar developed using Bootstrap and the CSS opacity DOES NOT WORK on the component 'app-search-city-bar'-->
<div class="searchBar row align-content-lg-center">
<div class="col-lg-1">
</div>
<div class="col-lg-2">
<app-button-search-city-polygon-component></app-button-search-city-polygon-component>
</div>
<div class="col-lg-4">
<app-search-city-bar [ngClass]="[cityBarStyle]"></app-search-city-bar>
</div>
<div class="col-lg-1">
<app-clear-polygon-bar [ngClass]="[polygonBarStyle]"></app-clear-polygon-bar>
</div>
<div class="col-lg-2">
<app-button-search-centers-or-operators></app-button-search-centers-or-operators>
</div>
<div class="col-lg-1">
<app-validate-and-search-button></app-validate-and-search-button>
</div>
<div class="col-lg-1">
</div>
</div>
This is the CSS of this component:
.searchBar {
background-color: #eeeeee;
padding-top: 15px;
display: flex;
justify-content: center;
}
.cityBarDisabled {
opacity: 30%;
pointer-events: none;
}
.polygonBarDisabled {
opacity: 30%;
pointer-events: none;
}
.cityBarEnabled {
}
.polygonBarEnabled {
}
This is the TS code:
import {AfterViewInit, Component, OnInit} from '#angular/core';
import {Subscription} from 'rxjs';
import {ToggleCityPolygonService} from '../../_service/toggleCityPolygonService/toggle-city-polygon.service';
#Component({
selector: 'app-search-bar',
templateUrl: './search-bar.component.html',
styleUrls: ['./search-bar.component.css']
})
export class SearchBarComponent implements OnInit {
state = '';
cityBarStyle = '';
polygonBarStyle: '';
constructor(private toggleCityPolygonService: ToggleCityPolygonService) {
}
ngOnInit(): void {
this.toggleCityPolygonService.getCityPolygonStateObs().subscribe(v => {this.state = v[''];
// console.log('i\'m gettin value: ' + v);
if (v === 'searchByCity') {
// #ts-ignore
this.polygonBarStyle = 'polygonBarDisabled';
this.cityBarStyle = 'cityBarEnabled';
} else {
if (v === 'searchByPolygon'){
this.cityBarStyle = 'cityBarDisabled';
// #ts-ignore
this.polygonBarStyle = 'polygonBarEnabled';
}
}
})
}
}
The 'toggleCityPolygonService' is the service which holds the 'cityPolygonState' that change between two values when the user click on the relative toggle button which can assume only two states: 'searchByCity' and 'searchByPolygon'
Opacity takes value 0.1 - 1. Try changing opacity: 30% to opacity: 0.3;
https://www.w3schools.com/css/css_image_transparency.asp
This is not the issue caused by Bootstrap. It's because of css optimiser (cssnano) on production build.
To avoid this, you can use the values between 0 and 1.
In your case, you can use 0.3 instead 30%.
opacity: 0.3; // opacity: 30%;
MDN guild on opacity
Issue reported on GitHub

Append symbol to end of input which leads value

I have an input field that accepts a percent, but I'd like to indicate to the user that the value they are entering is a percent.
The problem I'm having is that I'd like the percent to lead the text, so in the input it looks like this: 100% or 10000%, but I don't want the % to be part of the actual input.
Is there a way to achieve? I've tried a couple of options to do this with CSS but fall short when the % value doesn't actually adjust the placement in the input. Instead it's always appended to the very end of the input field instead of catching up with the input.
The component looks like this:
class Input extends Component {
constructor(props) {
super(props);
this.state = {
isActive: false,
}
}
render() {
return (
<div>
<input
value={this.props.value} >
</input>
</div>
)
}
}
CSS:
div {
input:after {
content: '%';
position: absolute;
top: 3.4rem;
z-index: 9999;
color: blue;
font-size: 2rem;
}
}
Example of what I'm trying to achieve, the highlighted text in the example below is what I want the user to be able to edit, and the % to dynamically move depending on the length of the input.
It's easy by using data-attribute on a container (because input cannot handle :before and :after, [More here]) and CSS content:attr()
update = function(el) {
el.parentElement.setAttribute('data-value', el.value)
}
div[data-value] {
position: relative;
}
div[data-value]:after {
content: attr(data-value) "%";
position: absolute;
top: 2px; /* Borders */
left: 2px; /* Borders */
}
div[data-value] input {
color: #FFF; /* Optional bug avoid visual bugs */
}
<div data-value="0.01">
<input value="0.01" oninput="update(this)"/>
</div>
PS: I did it on vanillia but it's easy to update in React
Using jQuery:
$("#input").on("keyup", function(){
$(this).val($(this).val().replace(/[^0-9]/gi, '') + '%')
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="input"/>
This would make it so there's always a % sign at the end and they cannot remove it or add anything except for numbers!
You can also convert this to regular Javascript if you wanted to