I am using Vue & Bootstrap for an app where I generate web components according to the official Vue documentation (https://cli.vuejs.org/guide/build-targets.html#web-component). For the most part Bootstrap and my business logic is working fine within the #shadow-roots of the web components as if it were in the light DOM.
However, Bootstrap tooltips (which are based on Popper.js https://popper.js.org/) are not working within the Shadow DOM at all. I have also tried to invoke tooltips directly with Popper.js and Tippy.js (https://atomiks.github.io/tippyjs/) in the Shadow DOM encapsulated code, sidestepping Bootstrap altogether, and I still cannot get them to work.
See example here: https://jsfiddle.net/mfep6rg9/
I can guess why -- the 3rd party tooltip libraries most likely aren't finding the target DOM element because it's in a Shadow DOM.
Is there a 3rd party solution out there that accounts for Shadow DOM / web component encapsulation?
Your guess is correct. 3party solutions using document. are not querying shadowDOM.
And there probably is no 3rd party solution as a solution requires either
WebComponents to communicate Mouse positions to the outside world.
Host querying shadowDOM (and nested shadowDOMs and nested shadowDOMs)
Not much different from an (even more restricted) IFRAME
I had the same problem while building LitElement-based Web Components and found the following solution:
$(this.shadowRoot.querySelectorAll("[data-toggle='tooltip']")).tooltip();
Make sure to target the respective element's shadowRoot and run a querySelectorAll to listen to all shadowRoot child elements that listen to "data-toggle='tooltip'".
Related
I am using ReactJS and it is not recommended to use JQuery (or vanilla JS) to maniplate the actual DOM, because it may have unpredictable results because of ReactJS using a virtual DOM.
So, if I include pure Bootstrap in my project, could it have the same adverse effect? If so, the use of reactstrap or react-bootstrap would solve this problem or do those libaries also use the bootstrap javascript under the hood?
Thank you,
Michel
The key thing to Avoid is manipulating the DOM for objects (or html DOM elements) that have been created with react, and have states tracked by react. Outside that you are free to use as much jquery or vanilla javascript as you like for DOM manipulation.
This is because, objects rendered with react js tend to work with the state of the object, and attempting to get things to work like toggling classes can cause clashes, if the element state that reactjs remembers has been altered by javascript or jQuery.
For example: What this means is that you can use react to render bootstrap tabs that use bootstrap javascript and jquery,
Then you can activate the tabs after react has rendered them with jquery. You'll have to limit your react to only the render function and avoid setState or update.
using setState or render after the initial render will have to be avoided, if jquery is used to toggle the classes, and react attempts to do the same later, clashes will occur.
In summary you can use both reactjs and JQuery in the same project , but stick to one (either pure react or pure jquery) per element for post render manipulations
Yes it could cause a conflict with React, but it very much depends on what you want to use in Bootstrap? if you just want to use the styling then that will not cause you issues.
Bootstrap JS functions such as showing and hiding divs ( Accordion for example ) might give you issues if React is going to be expecting that div to be in a certain state on the render.
But i have hobby projects that use React and jQuery just fine as long as i am not asking each of the libraries to overlap. Once i have built an application i then try and remove the jQuery from it and move the function into React with the aim to remove jQuery completely.
If you want to expand your answer to provide an example of what you are working on then i'm happy to add to my answer.
So I have two shadowRoot nodes
one created via createShadowRoot() - v0
another created via attachShadow() - v1
Now, if I look at properties and __proto__ of these both nodes - there's no visible difference. How do I tell by which version was that shadowRoot created? I'm making a third-party service which mirrors the content of a given page, which means I have to create right version of shadowDOM in the mirror page in order to know whether <content> or <slot> elements are going to be used (they may get inserted in dynamically).
I'm experimenting with Polymer. I love how the web components work. Now I want to build a web app. My question is: Should I have a main element (called app-element for example) that hosts all other elements and works as an orchestrator? One big element in the main html document that contains the JS code to handle all other elements? If yes do these elements exist in iron-elements or something? If not then how do I manage the JS code that handles the elements? pure js?
For people that used Angular 1, I remember the "app" controller? that was set to the body tag? This was a global controller to control all directives inside that html document. My question is do I follow a similar pattern with Polymer?
Taylor Savage (Polymer Product Manager) addresses this in the Polymer Summit 2015 opening keynote (the video is timed to kick off exactly where Taylor discusses the topic).
Up to now the Polymer team has viewed Polymer as "legos". You can put them together however you want. E.g. if you want routing, you can wrap your favorite routing library in an element. Polymer is a "swiss army knife" of tools that you use as you need. It's not a framework. It doesn't enforce app-level architecture. It's up to you decide. Which makes it hard on developers to know where to start.
So, here's three options off the top of my head:
Design your own architecture however you see fit
Wait for the "Carbon" elements that are designed to address application architecture (mentioned in the keynote)
Check out the Polymer Starter Kit. You'll see a lot of "container" or "parent" elements (e.g. elements that contain and unite children or "leaf node" elements). The main document is essentially just a declaration of all of these top-level container elements.
I've been hearing about Shadow DOM recently. While watching a video about the release of Angular 2 the presenter repeatedly made mention of Shadow DOM without clear expressions. What does Shadow DOM really mean?
The best explanation I've found is this from What the Heck is Shadow DOM? shown below:
Shadow DOM refers to the ability of the browser to include a subtree
of DOM elements into the rendering of a document, but not into the
main document DOM tree.
An important use case would be with video controls on a web page. The markup only shows a video tag, with some attributes and source tags. The addtional code for all the video operations to work is hidden in the Shadow DOM and not available to the rest of the page. The actual markup, javascript, and styles for the tag are encapsulated, which hides the implementation details of the video controls that each browser vendor has already written.
So while it's there in the DOM, its hidden from the page that renders it. So, to view the Shadow DOM, you can enable it under Dev Tools in Chrome.
The short answer is that the Shadow DOM is one of four technologies that make up Web Components.
For a definition, Web Components are: A component platform from the W3C that allows Web sites to be constructed from standardized building blocks. Web Components comprise Custom Elements, Shadow DOM and HTML Imports and Templates.
Shadow DOM is a technology of Web Components (although each can be used separately):
Custom Elements: is a capability for creating your own custom HTML tags and elements. They can have their own scripted behavior and CSS styling. They are part of Web Components but they can also be used by themselves.
HTML Templates: The HTML template element is a mechanism for holding client-side content that is not to be rendered when a page is loaded but may subsequently be instantiated during runtime using JavaScript. Think of a template as a content fragment that is being stored for subsequent use in the document.
Shadow DOM: provides encapsulation for the JavaScript, CSS, and templating in a Web Component. Shadow DOM makes it so these things remain separate from the DOM of the main document. You can also use Shadow DOM by itself, outside of a web component.
HTML Imports: is intended to be the packaging mechanism for Web Components, but you can also use HTML Imports by itself. You import an HTML file by using a tag in an HTML document.
See Introduction to the Shadow DOM.
It refers to the ability to create a "child" DOM completely sandboxed from the rest of the page. Useful for web components, reusable "widgets" which allow to not worry about their css/js affecting things they shouldn't. http://glazkov.com/2011/01/14/what-the-heck-is-shadow-dom/
Check out https://www.polymer-project.org/ if you want to see it in action.
Think of shadow DOM is as an encapsulated (private) DOM.
You can't access the shadow DOM in the manner you access regular DOM, like 'document.querySelector()'.
Let's say, you defined a reusable custom element, (which contains its DOM trees). Then you use the custom element within your app HTML.
Now, the DOM under (which is now called a "host element") has become a shadow DOM subtrees (under a shadow root), hidden from the parent structure!
I hope this help you a bit.
I would like to create a angularjs widget that can be embedded in third-party websites with minimal code such as
<script src=mywidget.js type=...></script>
<div id="mywidgetContainer"></div>
or similar.
I found some resources such as this article for developing a widget using jquery http://alexmarandon.com/articles/web_widget_jquery/.
How would it be done using Angularjs? In what clever ways can angular features such as directives/views etc. be harnessed to this purpose? What are the gotcha's if any? Your thoughts/suggestions/opinions/experiences, please.
You should also keep in mind the possibility that the 3rd party website also uses angular,
and potentially a different version.
Check Multiple versions of AngularJS in one page
This is what seems to have worked for me. In the script I set the innerHTML property of the Container div to the angular view markup code. The key point is to use angular.$bootstrap to manually bootstrap the app after the page load. I did not see any particular value in creating a directive. A directive would need to be part of the view code that would still need to be assigned to the container using innerHTML.