Update from 01.2020: It should be fixed with https://github.com/Polymer/lit-element/pull/712
If undefined returned from render method of LitElement during the first render of the component and then lit-html TemplateResult is returned with some css classes (styles are defined in styles static getter method), these styles are not applied.
There is a simple JSFiddle to reproduce this issue.
If render method returns lit-html TemplateResult after first render of component, then <style> tag exists in shadow DOM.
If render method returns undefined after first render, <style> tag is missed in shadow DOM and never added even if lit-html TemplateResult in next render call.
For Chrome it works fine. The issue reproduces for Safari and Firefox.
UPDATE: It should be fixed with https://github.com/Polymer/lit-element/pull/712
The solutions is to make sure you always return lit-html TemplateResult from render method even if it's empty!
render() {
return html``;
}
But I don't fully understand why exactly this issue appears? Could somebody clarify?
There are three separate cases of how styling is handled based on Shadow DOM support, via source code:
(1) shadowRoot polyfilled: use ShadyCSS
(2) shadowRoot.adoptedStyleSheets available: use it.
(3) shadowRoot.adoptedStyleSheets polyfilled: append styles after
That's why it can behave differently in different browsers.
LitElement has a method adoptStyles(). It applies styling to the element shadowRoot using the static get styles property.
In your example, you could call this.adoptStyles(); after changing the property and it should render correctly.
https://wicg.github.io/construct-stylesheets/#using-constructed-stylesheets
https://github.com/Polymer/lit-html/blob/master/src/lib/shady-render.ts#L127
Anyhow, I think you faced a bug within the update method of LitElement.
This could solve it: https://github.com/Polymer/lit-element/pull/849
Related
Hi I am using an UI Library (forced to, company issue..) which provides an Angular component, which renders a form.
Now I want to disable all of the input fields an buttons inside this form. But the component of the library doesn't provide me the possibility to pass a parameter to change the status to read only.
Now I have no other option to do dirty DOM hacking. However it doesn't seem to work.
Here is my HTML of my own component, where I render the Library Component:
<component-of-the-library #formComponent></component-of-the-library>
Now inside my own components class I reference it:
#ViewChild('formComponent', {read: ElementRef}) formComponent: ElementRef;
However when I use the nativeElement feature and the querySelectorAll() function I don't see the button elements:
ngAfterViewInit() {
console.log(this.formComponent.nativeElement);
console.log(this.formComponent.nativeElement.querySelectorAll('button'))
}
The first line outputs the DOM of the library component. There I also see the buttons.
However the second line just returns an empty NodeList.
Am I missing something?
Instead of doing all these, come up with a div overlay and with the size of your form and make show or hide it based on your needs.
It will be easier than disabling each form inputs and buttons. Also the overlay is not the component but your div.
I able to read the DOM Nodes present in the child component from the parent Component using ViewChild() https://stackblitz.com/edit/angular-edmyur?file=src%2Fapp%2Fapp.component.ts
EDIT: I see another problem. AfterViewChecked gets called multiple times...
I found the answer myself. The problem is the LifeCycleHook. AfterViewInit works for your own component, but it doesn't wait for the child components to finish rendering.
When I use AfterViewChecked it works!
However I am still puzzled, that logging the nativeElement has always given me the correct DOM, even though it's still not rendered.
I am trying to create a custom React component with inline styling using Radium. I have React, Radium and Meteor working perfectly apart of this little thing.
What I want to achieve:
<div style={styles.tile}>
...
var styles = {
tile: {
background: this.props.color
}
And then create new components in the parent like this:
<Tile color="#A200FF"></Tile>
What I get is:
Error: Invariant Violation: findComponentRoot(..., .0.0.0.0.$/=11.0.$=10.0): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser), usually due to forgetting a <tbody> when using tables, nesting tags like <form>, <p>, or <a>, or using non-SVG elements in an <svg> parent. Try inspecting the child nodes of the element with React ID ``.
Now if I remove this.props.color and type in '#FF0000' it will work perfectly fine. But I really need to be able to pass the color to the component from the parent.
As I said: Meteor, React and Radium are working perfectly fine in other places of the app.
Any ideas how to achieve what I want to build? Is it Radium's bug or is it me not understanding something important about it?
I saw example code on https://github.com/lukemelia/jquery-ui-ember. Can some one tell me what is this.$()
you can see this on jquery-ui-ember-master\jquery-ui-ember-master\js\app.js
this.$() is a call of the $-method of your current objectscope.
this refers to your current object.
$ is a function of this.
() will call the function $ of this.
When you create a Component, in its code this.$() gives you a jQuery object reference, set to the element that was inserted into the dom by that Component (its outer tag, usually a div unless you told it otherwise). You can then use for example this.$('.myclass') to find the element with the class myclass within the section of HTML that is handled by that Component without having to specify an id attribute to find the correct set of elements.
This probably also applies to the Views, but you should be using a Component instead whenever possible.
As Leeft said this.$() will give you the reference to the jQuery object, but typically you should only want to get the reference to the jQuery object in didInsertElement where the component has been inserted into the DOM and you can do jQuery-UI stuff on the element.
In the past I've been able to modify the CSS on a page via an inline style tag.
I know this sounds horrible but it's for custom CSS writing while working on a kind of WYSIWYG (not with text though).
I used to do something like:
tag.styleSheet.cssText = myrules;
I don't know when exactly, but at some point IE started saying "Invalid Argument" when I try this. The real crux is that doing tag.innerHTML = 'body {}' gives Unable to set value of the property 'innerHTML': object is null or undefined which doesn't happen in any other browser.
EDIT
To be clear I am using an inline style tag. I am not trying to use the inline style attribute.
<style type="text/css" id="mytag"></style>
How can I change the inside of that tag?
EDIT 2
Please see this fiddle:
http://jsfiddle.net/tTr5d/
It appears that my solution of tag.styleSheet.cssText is identical to using styleSheets property. You can comment out the last definition of cssText to see it working as proposed by #Teemu. So now I'm real lost why it's not working in my app. If anyone has ideas what could break that functionality that would be great. In the meantime I'll be tinkering around my app.
IE is limited to 32 stylesheets. I like to forget that fact apparently, which seems to include inline style tags, on top of <link>.
I changed my sandbox to turn on minification so it would put the files together.
Then my code worked.
So it appears that when you go over the limit and insert via JS, you don't get a real error until you try what I did.
You can get a reference to a styleSheet object only via styleSheets collection (or imports collection). If you refer direct to the style element, you'll just get a HTML-element. (Check properties in both objects within simple for..in-loop, and see the difference)
This works in all IEs, and results are rendered immediately:
document.styleSheets['mytag'].addRule('BODY', 'background-color:red');
More info in MSDN: styleSheet object
You can use jQuery. If it's the inline style, you can use the .attr() function.
$("#myElement").attr('style')
otherwise, you can see what .css() has to offer. You can use that to get and set various CSS styles.
Other CSS related jQuery methods
I never had much luck with style elements and IE's innerHTML.
The dom methods are surer, even if you need to branch for IE;
without jquery-
function addNewStyle(str, title){
var el= document.createElement('style');
if(title) el.title= title;
if(el.styleSheet) el.styleSheet.cssText= str;
else el.appendChild(document.createTextNode(str));
document.getElementsByTagName('head')[0].appendChild(el);
return el;
}
I have an instance of CKEditor on a page. I am trying to give the CKEditor's body a class or ID so it matches some styles I have defined in a stylesheet.
There is a API documentation that should give access to the respective DOM elements, but I can't seem to get it working. All objects I try to query that way turn out undefined.
Does anybody know how to do this, or how to properly address CKEditor's dom elements?
Edit: Thanks folks, nemisj's answer did it for me but for some reason, I don't get to set the "accepted" checkmark in this question.
Although that part of the API wasn't ported from 2.x at the time that this question was placed, now it's easier to use the bodyId and bodyClass config options.
Of course, the explanation by nemisj is good and can be useful for other things, but you must remember that each time that you switch away from design (to source view), the iframe is destroyed, so you'll need to reassign your attributes if you do it manually.
If you are talking about CKEditor( version 3), then there is a possibility to get any DOM instance inside the editor itself. Every CKEditor instance has reference to it's document via "document" property.
var documentWrapper = edit.document;
This reference represent some public wrapper for all CKEditor nodes, but it also has the direct reference to its node. You can retrieve by getting ["$"] property.
var documentNode = documentWrapper.$; // or documentWrapper['$'] ;
documentNode will represent the DOM instance of the document node inside the iframe. After you have the DOM instance, you can do whatever you want to do with DOM structure, Append, remove, replace classes, rebuild, etc. For example
documentNode.body.className = "zork";
I hope this should be enough.
I had the same problem today in trying to set the bodyClass like this:
CKEDITOR.replace( 'editor1',
{
fullPage : true,
bodyClass : 'myClass'
});
What I found is that in this version (3.3.1), if you set fullpage = true, setting the bodyId or bodyClass does not work, but if you set fullPage = false, it does work.
Hope this helps.
From the Manual:
<static> {String|Array} CKEDITOR.config.contentsCss
The CSS file(s) to be used to apply style to the contents. It should reflect the CSS used in the final pages where the contents are to be used.
config.contentsCss = '/css/mysitestyles.css';
config.contentsCss = ['/css/mysitestyles.css', '/css/anotherfile.css'];
Default Value:
<CKEditor folder>/contents.css
Don't know that editor, but as they all work the same way, you probably can't access the DOM elements created by the instance because they are created after the page has finished loading, and the DOM is ready as well. So, any new DOM elements added after that, theorically will not exist.
Still, you can try TinyMCE editor, wich has a "partnership" with jQuery javascript library to manipulate all you want, and the editor itself is pretty easy to change in almost every way.
Your queries may return undefined because the editor instances are placed inside an iFrame and your query is not looking there?
In config.js, write this code
config.bodyId = 'contents_id';
then you see body id in Ckeditor but when you want to access this id please use
$('#parent_id').find('iframe').contents().find('#within_iframe')
there $('#parent_id') means form_id or any parent which is simply way to access iframe. follow this code to access element in iframe