react-select styling from classes - css

I have given className as react-select-container and classNamePrefix as react-select. The styles described in the CSS is getting overwritten by the inbuilt style of the react-select. Image shows react-select__control styles is getting overwritten by the styles of some default class css-yk16xz-control of the react select. i want it to work the other way around and react-select__control styles stay on top and its styles get applied. any suggestions.
render() {
const titleOptions = [{value: 'Dr.', label: 'Dr.'}, {value:'Eng.', label:'Eng.'}, {value:'Officer', label:'Officer'}];
return (
<Select options={titleOptions} autoFocus className="react-select-container" classNamePrefix="react-select" />
)
}
Check Dom structure here
.react-select__control {
border: none;
border-radius: 3px;
}

Related

Is there some way with which i can apply css dynamically to my child component?

I have a component which is reusable. This component is called from parent component multiply times and sometimes the background page of the parent component is white and sometimes is black.
My child component generates form tags dynamycally - inputs,selects, textarea.
That means i can't have fixed styles in my css in my component for my content.
So when when the background page is white - i have one style for my inputs - for example black background. When the background page is black i have another style for my inputs - for example white bacgrkound.
To solve this is issue:
i tried
Adding input property in my child component ts file
#Input()
public cssTemplate;
in html
<div [ngClass]="{'form-group-white-bg': cssTemplate == 'white', 'form-group-dark-bg': cssTemplate == 'black'}">
<label for=""></label>
....
In the CHILD component i am sending value for input property depending on where the child component is called
if it is called on page with white background
<app-form-group cssTemplate="black" formControlName="address">
</app-form-group>
if it is called on black bacgrkound
<app-form-group cssTemplate="white" formControlName="address" [data]="{ field: 'address', label: 'Address' }">
</app-form-group>
but the problem here is that sometimes on my parent component this component is called multiply times
on one page can be called 12 times where i need 10 inputs and 2 selects
on other page can be called 15 times etc.
That means that i need to repat my self 15 times
<app-form-group cssTemplate="white" formControlName="address">
</app-form-group>
<app-form-group cssTemplate="white" formControlName="someItherControlName">
</app-form-group>
and everywhere to put cssTemplate="white".
ngFor is not an optin because this child component is called multiply times but not on same place in the HTML structure in the parent.
How can i solve this DRY?
you can add styles in your styles.css (the styles general for all the application). If e.g. you has
.white h1{
color:red;
}
.black h1{
color:green;
}
You can use [ngClass] in the "parent"
<div [ngClass]="toogle?'white':'black'">
<hello name="{{ name }}"></hello>
</div>
<button (click)="toogle=!toogle">toogle</button>
See [stackblitz][1]
NOTE: I used the way [ngClass]="expresion" (where expresion use conditional operator) better that [ngClass]="{'classname1':condition;'classname2':!condition}"
Update about your comment "how can i prevent repeating my self on child call", really I don't understand so much. I don't know if you want to make a directive like, e.g.
#Directive({
selector: 'hello', //<--the selector is the selector of the component
exportAs: 'helloDiv'
})
export class HelloDirective implements OnInit{
constructor(#Self() private component:HelloComponent,private dataService:DataService){
}
ngOnInit(){
console.log(this.component.name)
this.dataService.theme.subscribe(res=>{
this.component.theme=res;
})
}
}
This allow to "extends" the component -in the stackblitz the variable "theme" change-
[1]: https://stackblitz.com/edit/angular-ivy-sjwxyq?file=src%2Fapp%2Fapp.component.html
You can use an input property to create a css class map to pass on to ngClass. This object should be an object of string arrays.
It can be pretty much as complex and contain as many classes and rules as you need it too
#Input() color: 'white' | 'red' | 'hotpink' = 'white';
classMap: any;
ngOnInit() {
this.updateClassMap();
}
updateClassMap() {
this.classMap = {
[this.color]: !!this.color, // Add this class if not null
};
}
Then in the Html simply pass it to ngClass
<div [ngClass]="classMap">
Styling Child Components depending on Parent Component
There are two approaches I commonly take in this scenario
:ng-deep - create a style rule based on a class which is set in your parent component
utilize #ContentChildren() to set a property directly on your child components and call detectChanges() manually after the change.
To adopt the first solution you need to exercise greater care in your css naming rules, as using ng-deep obviously breaks the isolation of those style rules.
To adopt the second approach needs some considering due to it technically circumventing the standard input/output flow in Angular and thus can be a bit of a surprise "undocumented behavior" for any other maintainers of the application.
I'm a bit on the fence whether I prefer one approach over the other. The first approach seems more trivial to me, but it can also cause unintended style rule overwrites, while the second approach involves a lot more scripting and seems a bit of a hack.
Approach 1: ng-deep
Give your parent component an input and update a class on a block-element wrapping your <ng-content>.
create your desired style rules in your child component.
// parent component
#Component(...)
export class FooParent {
#Input() bgStyle: 'light' | 'dark' = 'light';
}
<!-- parent component template -->
<div class="parent" [ngClass]="{light: bgStyle == 'light', dark: bgStyle == 'dark'}">
<ng-content></ng-content>
</div>
// child.css
::ng-deep .light .child-container {
background-color: lightblue;
}
::ng-deep .dark .child-container {
background-color: royalblue;
}
My targeted element in the example is .child-container, you would write a similar style rule for each element you want to affect.
Approach 2: Using ContentChildren to pass along a value
Add a #ContentChildren() decorator to your parent component which selects for your child components.
inject a ChangeDetectorRef
implement ngAfterViewInit to loop through each child and set the value
call detectChanges() once done.
add the ngClass directive as normally in your child component.
Parent
#Component({
selector: 'parent',
templateUrl: 'parent.component.html',
styleUrls: ['parent.component.scss']
})
export class ParentComponent implements AfterViewInit, OnChanges {
#Input() bgStyle: 'light' | 'dark' = 'light';
#ContentChildren(ChildComponent) childComponents!: QueryList<ChildComponent>;
constructor(private change: ChangeDetectorRef) {
}
ngOnChanges(changes: SimpleChanges) {
if ('bgStyle' in changes) {
this.updateChildComponents();
}
}
updateChildComponents() {
this.childComponents.forEach(child => {
child.bgStyle = this.bgStyle;
});
this.change.detectChanges();
}
ngAfterViewInit() {
this.updateChildComponents();
}
}
<!-- parent.component.html -->
<ng-content></ng-content>
Child
#Component({
selector: 'child',
templateUrl: 'child.component.html',
styleUrls: ['child.component.scss']
})
export class ChildComponent implements OnInit {
bgStyle: 'light' | 'dark' = 'light';
constructor() {
}
ngOnInit(): void {
}
}
<!-- child.component.html -->
<div [ngClass]="{light: bgStyle == 'light', dark: bgStyle == 'dark'}" class="child-container"></div>
// child.component.css - you would apply styles as you needed obviously.
.child-container {
width: 40px;
height: 40px;
margin: .5rem;
}
.light.child-container {
background-color: lightblue;
}
.dark.child-container {
background-color: royalblue;
}
Usage
<!-- any other template -->
<parent>
<child></child>
<child></child>
<child></child>
</parent>
Note: If you are creating the ChildComponent directly in the ParentComponent's own template you need to use #ViewChildren instead of #ContentChildren

Applying CSS stylesheet only to active component

I'm working on a ReactJS app that has a header at the top, a menu on the left, and the "frame" in the middle is where routes and their corresponding components are loaded. I want to be able to apply a CSS stylesheet to specific components only when they are loaded. I also don't want them applied all the time or to the top header or left menu.
My expectation was that adding import 'custom.css'; to a specific component would only apply the stylesheet's styles to that component and it's children when the route is active. Instead, it applies it to the entire page even when the route/component are not loaded.
I understand that an alternative approach is styled components, but, for my use-case, a design company is supplying a stylesheet (which should remain unchanged) that we need to consume only for the sub-module I'm working on and I don't want its styles to affect the rest of the app.
How can I have a stylesheet only applied to my active route/component?
Use simple CSS technique. Suppose you have two components with different css files (say about.css and contact.css). Now consider your both CSS file have one common class with different style properties, like:
about.css
.container{
max-width: 400px;
}
contact.css
.container{
max-width: 500px;
}
Yes in ReactJS both the CSS files will load at the same time and will override any one of the style. so to solve this problem add class to differentiate this styles, like:
about.css
.about-component.container{
max-width: 400px;
}
contact.css
.contact-component.container{
max-width: 500px;
}
If you want apply only when the component is mounted, you can use the lifecycle.
The follow example is based in the idea you are using sass, React, sass-node and have the loaders into webpack.
<pre>
import React from 'react';
import './styles.scss';
class MyComponent {
constructor(props) {
super(props);
this.state = { className: '' }
}
componentDidMount() {
this.setState({
className: 'myOwnClass'
});
}
render(){
return (
<div className={this.state.className}>This is a example</div>
);
}
}
export default myComponent;
</pre>
To be able to only call that specific CSS when you need it you can use CSS Modules. You may need to update your version of react.
When saving your CSS file save it with a ".module.css" eg. "styles.module.css". The CSS in these files can only be used and accessed by hte components where are they are imported. As stated in a tutorial from W3Schools.
Let's say this is your CSS code in styles.module.css:
.container {
color: white;
}
.cont-child {
background-color: red;
}
Then in your JS file you can import the CSS file like this if the JS and CSS files are in the same directory. Make sure you point to the correct path.
import styles from './styles.module.css'
Then in your HTML section you can use it like this:
class Home extends React.Component {
render() {
return(
<main className={ styles.container } >
<div className={ styles["cont-child"]} >
Some div text about something...
</div>
</main>
);
}
}
I currently use both ways to access the selectors, since the styles variable acts like an object. I placed both of them here because the second option is capable of fetching selectors named like "btn-active". Which comes in handy in some situations. Camelcasing is considered cleaner though.
Please note: I originally posted this answer as a reply to a similar question here React CSS - how to apply CSS to specific pages only
I want to be able to apply a CSS stylesheet to specific components
only when they are loaded.
Why not apply the styles inline via React.js?
Step 1. Create the style object for the component:
var componentOneStyle = {
color: 'white',
backgroundColor: 'red'
};
Step 2. Populate the component's style attribute with the style object:
ReactDOM.render(<div style={componentOneStyle}>This is Component One</div>, mountNode);

How to dynamically change css selector property value in react js code?

I need to dynamically change the color in the react component for specific selector.
In scss (use sass) i have the following rule:
foo.bar.var * {
color: blue;
}
I want to change it in react code, to be yellow, red or something else.
I cant use style property for element, cause i need the selector to
apply for all subchilds !=)
Is there any native ways? Or should i use Radium? Or is there any similar libs for this? Maybe css-next some hove can help with this?
I have color picker, i cant write class styles for every color =(
For some answerers NOTE:
So i have selector in some scss file, that imported in some root js file with .class * {color: $somecolor} and i need change the $somecolor in that selector, during picking colors in color picker
Maybe i can somehow set selector for all nested inside style property? or there is the way how to recursively apply css style for every nested items from the style prop?
What about
class MyComponent extends React.Component {
render() {
const yellow = true // Your condition
return(
<div className={`foo bar var ${yellow && 'yellow'}`}
My item
</div>
)
}
}
.foo.bar.var {
& * {
color: blue;
}
&.yellow * {
color: yellow;
}
}
You could define a custom CSS property (CSS variables) using the style attribute of the element and assign the value to a prop, state etc.
<div className='foo bar var' style={{ "--my-color": props.color }}></div>
The custom property would work for any selector that apply to that component or children. So you could use it like that:
foo.bar.var * {
color: var(--my-color);
}
See a snippet with similar code here
this may sound stupid . but does this work ?
import myCss from './mydesign.css';
myCss.foo.bar.var = "your color"

Angular2 CSS style/class strings as inputs to component

Background
I have a component that wraps two span elements. I would like parent components to be able to style the inner two spans by specifying CSS classes and styles as inputs (preferably as simple strings). Here's a simplified example of what I would like this to look like:
Code
app component (parent)
#Component({
selector: 'my-app',
template: `
<div>
<app-two-spans [classArg1]="'class1'" [classArg2]="'class2'"
[styleArg1]="'width: 100px'" [styleArg2]="'width:200px'"></app-two-spans>
</div>
`, style: `
::ng-deep .class1 {
border: 1px solid black;
}
::ng-deep .class2 {
border: 1px solid blue;
}
`
})
export class App {
}
two spans component (child)
import {Component, Input, Output, EventEmitter} from '#angular/core';
#Component({
selector: 'app-two-spans',
template: `
<span *ngIf="flag" [ngClass]="classArg1" [ngStyle]="styleArg1"
(click)="flag = !flag">click me</span>
<span *ngIf="!flag" [ngClass]="classArg2" [ngStyle]="styleArg2"
(blur)="flag = !flag" contenteditable="true">
click me to change my value</span>
`
})
export class TwoSpansComponent {
flag: boolean = true;
#Input() styleArg1: string;
#Input() styleArg2: string;
#Input() classArg1: string;
#Input() classArg2: string;
constructor() {}
}
Problem
The class styling seems to work in my local environment (though it doesn't seem to work on Plunker for some reason). However, the styles are not showing up. I've seen other posts about styles as inputs, but from what I've seen this is usually done by passing style-value pairs (see accepted answer here). However, I would really like to pass these styles as a simple string to make working with the component easier.
I notice the following error in the console: ERROR Error: Cannot find a differ supporting object 'width: 100px'. I'm not sure what this means at all.
Plunker here
Is there a way to do this? How can I give parent components the ability to stylize children?
ngStyle accepts an Object instead of plain string. You can pass your styles as:
[styleArg1]="{ width: '100px' }"
[styleArg2]="{ width: '200px' }"

Component is briefly rendering without styles on first render

When I open my react app, the component below flashes with width:100%, probably because it inherits it from the material-ui card.
In my react app there are a lot of these components being rendered, each with their own width which are based on the parent component's data. I set the width with an inline style based on the props.
As I understand, the component has the inline style as it is created and there should be no delay to apply it. However I see all the SceneThumb components with 100% width for a a fraction of a second, before they apply the given inline style.
If I change the css of scene-thumb-parent to include some width, say 10% for example, then I'll see them all with 10% for a fraction of a second, before the inline style is applied. That makes me think there is a delay in applying inline css, but it really puzzles me..
Is this to be expected of react? Or of html in general? Is there any way to reduce this inline style application delay? Maybe it's something to do with the dev hot reloading setup I get from create-react-app?
SceneThumb.js (code that is irrelevant to the question has been omitted):
import React, { Component } from 'react';
import './scene-thumb.css';
import Card from 'material-ui/Card';
class SceneThumb extends Component {
render() {
return (
<div
className='scene-thumb-parent'
style={{width:this.props.width, left:this.props.left}}
>
<Card
className={this.props.selected?'scene-thumb-selected':'scene-thumb'}
>
<span>
Hello world!
</span>
</Card>
</div>
);
}
}
export default SceneThumb;
scene-thumb.css:
.scene-thumb-parent {
position:relative;
text-overflow:clip;
white-space:nowrap;
overflow:hidden;
min-width: 12px;
}
.scene-thumb-selected {
border: 2px solid red;
border-radius: 5px;
}
.scene-thumb,.scene-thumb-selected {
padding: 2px;
margin:2px;
position:relative;
}
The width prop is initially null or some other value. A moment later, the prop is updated which triggers another render. This is why you're seeing the flash you're talking about.
You can test this by adding the following to your render() function:
console.log(this.props.width)
You'll probably see it logging at least twice with different values.
There are many ways you can fix this. What makes most sense would depend on the rest of the application, and your personal preference. Regardless, here's one way:
render() {
if(!this.props.width) return null; //if it's null, render nothing.
return (
<div className='scene-thumb-parent' style={{width:this.props.width, left:this.props.left}}>
<Card className={this.props.selected?'scene-thumb-selected':'scene-thumb'}>
<span>Hello world!</span>
</Card>
</div>
);
}

Resources