React-css-modules makes up class names on the fly to limit name clashes while using standalone components. Thats awesome. But once the DOM is loaded and you need to target a class for an animation, for instance, the class names that css-modules comes up with are, in parts, randomized.
How to go about with this?
According from react-css-modules official doc, you can target class like bellow
render() {
const animated = this.props.styles['animated']
return <div className={animated}>something</div>
}
Query selector shouldn't be necessary with react just attach a ref to the element you want and you have access to it within any function of the react component.
https://facebook.github.io/react/docs/more-about-refs.html
So I ended up using the classNames npm module
to add and remove classes to an element when I need more than one. Works like this:
let myClasses = classNames({
'button': true,
'special': this.state.special
})
<button className={myClasses} />
Related
I'm working on new web-components and ran into some issues concerning slots.
I have an outer container-component with a "main-slot" inside, in which multiple elements should be inserted (into the same slot). However, it is only possible to add one element per named slot.
My question: is there a way to add multiple elements to one named slot? Like shown here:
<own-container>
<own-element slot="main"></own-element>
<own-element slot="main"></own-element>
<own-element slot="main"></own-element>
<own-element slot="main"></own-element>
</own-container>
There is also imperative <slot>
super().attachShadow({
mode: 'open',
slotAssignment: 'manual' // imperative assign only
})
But! you get Named slots OR Imperative slots, on one Web Component
To mimic named <slot>, assigning content to the same named <slot>
you probably need the Mutation Observer API
addendum
You can have multiple elements per slot:
<component-with-slots>
<H1 slot="title">Web Components are great!</H1>
<h2 slot="title">A bit hard to master</h2>
<b slot="title">But Great!</b>
</component-with-slots>
<script>
customElements.define('component-with-slots', class extends HTMLElement {
constructor() {
super()
.attachShadow({mode:'open'})
.innerHTML="<slot name='title'></slot>";
}
});
</script>
Nope. It is not possible for named slot. The trick is to have a wrapper div element to wrap your lightDOM.
<own-container>
<div slot="main">
<own-element></own-element>
<own-element></own-element>
<own-element></own-element>
<own-element></own-element>
</div>
</own-container>
If the presence of additional div causes styling problem, then you can use new contents type of display box.
div {
display: contents;
}
The display: contents causes an element's children to appear as if they were direct children of the element's parent, ignoring the element itself. However, note that it can cause accessibility issues.
I have custom attribute my-custom-attribute which contains the id for the element I need to add and remove this attribute depending on the boolean.
I already tried this code and it is working fine, is there any way to make it using vuejs directives?
HTML:
<div my-custom-attribute="my_element">
...
</div>
JS:
const el = document.getElementById("some_id");
if(my_bool) {
el.setAttribute("my-custom-attribute", "#my-element");
} else {
el.removeAttribute("my-custom-attribute")
}
You can register a directive as global using the below example, it provides you three lifecycle hooks for you to control the behavior, read the following and try to implement. Let us know if any problem occurs with your implementation and start a separate thread
https://v2.vuejs.org/v2/guide/custom-directive.html
Vue.directive('my-custom-directive', {
// When the bound element is inserted into the DOM...
inserted: function (el) {
// Focus the element
el.focus()
}
})
Shared component: pro-image
This component has image element with id proImg
<img id="proImg" src="{{imgPath}}">
imgPath is #input variable.
This component is used in multiple components and each parent passes image path and image dimension to above shared component.
In this shared component.ts file, I'm trying to access <img> element by id to add some attributes to the element. But while access element by Id only last element is getting accessed.
I want to uniquely this image element each time its been used in other component similar to host selector. Please suggest how can I achieve.
Your issue is that they all have the same id property. id should be unique, per Mozilla docs for getElementById https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
One option, instead of using the id, use a ViewChild to access the DOM Element.
Change your template to this
<img #proImg [src]="imgPath">
And in your component you can access it this way:
class MyCmponent {
#ViewChild('proImg', {static: true}) proImg: ElementRef;
ngAfterViewInit() {
// you can access the native dom element like this:
this.proImg.nativeElement.style.height = "100px";
this.proImg.nativeElement.style.width = "100px";
}
}
Another option, if you are just setting styles or other properties, you can bind them in the template
<img [src]="imgPath" [ngStyle]="styles" [ngClass]="classes">
Component
class MyComponent {
styles = {
width: "100px",
height: "200px
}
classes = ['class1', 'another-class']
More on ngStyle https://angular.io/api/common/NgStyle
More on ngClass https://angular.io/api/common/NgClass
I'm migrating an old "jQuery" application, adding some React components. I have some JS/jQuery code adding some elements in the DOM. I want to replace this using for example a new Item component, creating many instances and adding them to the same container. And I need to get the real DOM element to manipulate it (with the old JS/jQuery code).
I found this solution :
const elt1 = ReactDOM.findDOMNode(ReactDOM.render(<CalendarItem item={item} />, container))
but the container content is replaced with the new Item and adding many items, only the last is finally in the container.
I have tried portal :
const elt2 = ReactDOM.createPortal(<CalendarItem item={item} />, container)
but the returned element elt2 is not a DOM element (that I can manipulate after).
Is there a solution to do this ?
Thanks
If you want to manipulate React components using their related DOM elements, look into Refs (https://reactjs.org/docs/refs-and-the-dom.html).
So create the ref in the constructor:
constructor(props) {
super(props);
...
this.calendarItem = React.createRef();
}
And then give the ref to your new CalendarItem:
<CalendarItem item={item} ref={this.calendarItem} />
You can then access the actual DOM node of that CalendarItem using this.calendarItem.current, for example:
$(this.calendarItem.current).focus();
Suppose a HTML element's id is known, so the element can be refereced using:
document.getElementById(element_id);
Does a native Javascript function exist that can be used to append a CSS class to that element?
var element = document.getElementById(element_id);
element.className += " " + newClassName;
VoilĂ . This will work on pretty much every browser ever. The leading space is important, because the className property treats the css classes like a single string, which ought to match the class attribute on HTML elements (where multiple classes must be separated by spaces).
Incidentally, you're going to be better off using a Javascript library like prototype or jQuery, which have methods to do this, as well as functions that can first check if an element already has a class assigned.
In prototype, for instance:
// Prototype automatically checks that the element doesn't already have the class
$(element_id).addClassName(newClassName);
See how much nicer that is?!
Adding class using element's classList property:
element.classList.add('my-class-name');
Removing:
element.classList.remove('my-class-name');
classList is a convenient alternative to accessing an element's list of classes.. see http://developer.mozilla.org/en-US/docs/Web/API/Element.classList.
Not supported in IE < 10
When an element already has a class name defined, its influence on the element is tied to its position in the string of class names.
Later classes override earlier ones, if there is a conflict.
Adding a class to an element ought to move the class name to the sharp end of the list, if it exists already.
document.addClass= function(el, css){
var tem, C= el.className.split(/\s+/), A=[];
while(C.length){
tem= C.shift();
if(tem && tem!= css) A[A.length]= tem;
}
A[A.length]= css;
return el.className= A.join(' ');
}
You should be able to set the className property of the element. You could do a += to append it.
addClass=(selector,classes)=>document.querySelector(selector).classList(...classes.split(' '));
This will add ONE class or MULTIPLE classes :
addClass('#myDiv','back-red'); // => Add "back-red" class to <div id="myDiv"/>
addClass('#myDiv','fa fa-car') //=>Add two classes to "div"
you could use setAttribute.
Example:
For adding one class:
document.getElementById('main').setAttribute("class","classOne");
For multiple classes:
document.getElementById('main').setAttribute("class", "classOne classTwo");