How do I append a Web Component created programmatically? - web-component

I created a Web Component class to extend div, and used customElements.define() to define it:
class Resize_Div extends HTMLDivElement {
constructor(){
super();
this.cpos = [0,0];
<etc.>
}
connectedCallback() {
console.log( 'connected' );
}
<etc.>
}
customElements.define('resize-div', Resize_Div, { extends:'div'} );
If I test in html, as <div is:'resize-div'> </div>, it works fine.
Now I want to use createElement to create an instance programmatically, using the options to declare the is, as documented here:
let dv = document.createElement('ul', { is: 'resize-div' })
The browser developer tools show it created, with outerHTML as below:
outerHTML: "<div is="resize-div"></div>"
As documented, "The new element [has] an is attribute whose value is the custom element's tag name."
Now I set id, class, and style, and attach the new element to the DOM via:
document.getElementById( parent ).appendChild( dv );
Now look at it again: the is attribute is stripped off and it doesn't function as a Web Component:
attributes: NamedNodeMap
0: id
1: class
2: style
length: 3
The docs for the deprecated registerElement here show an example using document.body.appendChild( new myTag() ), but that's obsolete.
So what is the correct way to create a Web Component programmatically and attach it to a document?
(ps. I'm working on Chromium Version 70.0.3538.67 (Official Build) Built on Ubuntu, running on Ubuntu 16.04 (64-bit)

You've defined an extended <div> but you try to create a <ul> element.
If you create a <div> instead it will work:
let dv = document.createElement('div', { is: 'resize-div' })
The new syntax also works:
document.body.appendChild( new Resize_Div )
NB: When you create an customized built-in element programmatically the is attribute is not added in the HTML code but it still acts as a custom element, and outerHTML will return the HTML with is correctly populated as explained in the specs.

You can also create the element without this {is: 'tag'} object. May or may not be useful in some situations.
class MyElement extends HTMLElement {
constructor() {
super()
const shadow = this.attachShadow({
mode: 'open'
})
shadow.append(Object.assign(
document.createElement('h1'), {
textContent: 'Impossibru!'
},
))
}
}
customElements.define('my-custom-element', MyElement)
const el = document.createElement('my-custom-element')
document.body.append(el)

Related

How to mix pseudo class valid/invalid with Angular form control validator?

I'm using an Agular form control to control a "select" validity.
When said "select" is invalid, class "ng-invalid" can be found on the "select".
Class "ng-valid" is, when "select" is valid.
However, pseudo class remains ":valid" either way.
The problem is I'm using a third party library for style which is based on pseudo classes to handle style.
Take a look at this example,
https://stackblitz.com/edit/angular-xypbcc
I'd like that the pseudo class :invalid apply (and it's css style), when class is "ng-invalid", when select is empty.
(I know I could add the required to the select element, but I actually have other validators in my real use case)
Thanks
the easy way is copy the .css of inactive to .ng-invalid
A work-around is use setCustomValidity You can use a directive
#Directive({
selector: "[invalid]"
})
export class InvalidDirective implements OnInit, OnDestroy {
subscription$: any;
#Input("invalid") checkAtFirst: boolean = false;
constructor(private control: NgControl, private el: ElementRef) {}
ngOnInit() {
this.subscription$ = this.control.statusChanges.subscribe(res => {
this.el.nativeElement.setCustomValidity(res == "INVALID" ? "error" : "");
});
if (this.checkAtFirst && this.control.invalid)
this.el.nativeElement.setCustomValidity("error");
}
ngOnDestroy() {
this.subscription$.unsubscribe();
}
}
The directive inject in the constructor the ngControl (the input) and the elementRef (the HTMLElement) and subscribe to statusChange. I use the input if you want to check at first
So you use like
<select invalid=true formControlName="fcselect">
//or
<select invalid formControlName="fcselect">
You can see the example in the stackblitz

Add a class to the parent .wp-block element in gutenberg editor

When Gutenberg creates a class, it seems to be of the format
div.wp-block
div.editor-block-list__insertion-point
div.editor-block-list__block-edit
div.editor-block-contextual-toolbar
div
<your actual block html goes here>
I'd like to be able to add a class to that top div.wp-block element so I can properly style my block in the editor. The class is dynamically generated based on an attribute so I can't just use the block name class. Is there a clean way of doing this? I can hack it using javascript DOM, but it gets overwritten quickly enough.
https://wordpress.org/gutenberg/handbook/designers-developers/developers/filters/block-filters/#editor-blocklistblock
const { createHigherOrderComponent } = wp.compose
const withCustomClassName = createHigherOrderComponent((BlockListBlock) => {
return props => {
return <BlockListBlock { ...props } className={ 'my-custom-class' } />
}
}, 'withCustomClassName')
wp.hooks.addFilter('editor.BlockListBlock', 'my-plugin/with-custom-class-name', withCustomClassName)
You can add class in your block edit view by using className that is present in this.props, className will print class in following format wp-blocks-[block_name]
edit( { className } ) { // using destructing from JavaScript ES-6
return <div className={ className }></div>
}
Suggestion
Always try to look for manipulating DOM via React instead of manipulating DOM directly because React manages it's own state and issues can occur by manipulating DOM directly.

Add css to 1 page using scss and ReactJS and redux

I am using ReactJS with redux.
I using scss.
lets say my path is:
http://localhost:3000/login
I need to add to this page:
html:{ overflow:hidden}
and on other pages i want to remove this attribute.
Anyone have a clue?
You can change the style attribute of the html tag:
class MyPage extends React.Component {
componentWillMount() {
this.htmlTag = document.getElementsByTagName('html')[0];
this.htmlTag.setAttribute('style', 'overflow: hidden');
}
componentWillUnmount() {
this.htmlTag.setAttribute('style', '');
}
...
}
I don't know how is your project architecture, but you can add a class (className) into your HTML tag in differently ways.
If you want, you can also use your redux state.
You check if you are in X page, if it's ok, pass a boolean at true and if it's true, put your css.
I prefer the first solution.
You could just import a className, let's say loginStyle, and make it so:
html: {
overflow: hidden;
}
Then, you just put it as a condition let's say on your header (has to be an element present in every page).
Something like
const isLogin = window.location.pathname === login ? true : false ( <= this is not the real condition, but make it so isLogin equals true is you are on your login page).
<Header className={${className1} ${className2} ${isLogin ? loginStyle : ' '}}/>
And your style will only be applied on your login page. Maybe not the simpliest, but at least this would work :)

Binding on view with dependency

I am using a view to bind data to a contentEditable div using the code found in the answer to this question: Ember and HTML5 contenteditable property
I have a property a.b.c that I'm binding it to like so:
{{view App.ContenteditableView valueBinding="a.b.c"}}
This correctly updates a.b.c when I type in it, and it updates itself when I modify a.b.c. However, It does not update when I change a to a different object. That is, the text box needs to update when a or b changes, not just when c changes.
How is this done?
Ember already supports this if you properly use the built in setters.
if a extends Ember.Object a.set('b', { c: 'asdf'}) if a is a POJO Ember.set(a, 'b', { c: 'asdf'}).
Additionally using valueBinding isn't necessary, you can just write value=a.b.c
In the provided example I set the text box to a.b.c
App.IndexRoute = Ember.Route.extend({
model: function() {
return {
a:{
b:{
c:'dog'
}
}
};
},
actions:{
change: function(){
Em.set(this.currentModel, 'a', {b:{c:'fdasdf'}});
}
}
});
Example: http://emberjs.jsbin.com/toticame/1/edit

Add, remove css classes while Ember view getting rendered

How to add, remove and change css classes for an ember element based on the value from the contentBinding while doing ember each?
Doing something like below in didInsertElement, but by the time have added the css classes, based on content value from controller, view element is attached to the view and hence css doesn't get applied.
Is there any other way that we could perform this while view element is getting rendered?
didInsertElement: function() {
this._super();
var personStr= this.get("content").person;
if(personStr==1){
this.$("img").addClass("add-person");
this.$("img").removeClass("view-person");
this.$("img").removeClass("edit-person");
}
}
You could use a Ember.CollectionView and specify your classes which depend on the content in classNameBindings. See API documentation, section HTML class Attribute.
See an example here http://jsfiddle.net/pangratz666/b4xGP/:
Ember.CollectionView.create({
content: [{name: 'Brunö'}, {name: 'Alfred'}, {name: 'Hansi'}],
itemViewClass: Ember.View.extend({
templateName: 'item',
classNameBindings: 'beginsWithA'.w(),
beginsWithA: function() {
var name = this.getPath('content.name');
if (!Ember.empty(name)) {
return name.indexOf('A') === 0;
}
}.property('content.name')
})
}).append();​

Resources