When to use React 16 Portals - html

Lots of new functions released with React 16. One of them is the ReactDOM.createPortal(child, container) API, which is handy for visually breaking out of its container.
However, it seems like that it not only breaks out its container but also breaks the basic html rules which I learned from the first day of web development. The createPortal API let you render your component out of its parent, and break the html structure convention we expected.
In the other hand, we do retrieve more flexibility and now can render DOM in the sibling or else components.
IMO, I don't think this is a good deal to gain more flexibility by trading html convention in. Also the example supplied by official does not convince me.
What I am curious about is:
Is there anyone who face any condition that createPortal API is a must?
thanks

The examples in the docs are some of the cases where createPortal is really useful - specifically dialogs, hovercards, and tooltips.
The docs also specifically state:
Note:
It is important to remember, when working with portals, you’ll need to make sure to follow the proper accessibility guidelines.
As an example, the docs show how a modal could be built using createPortal(). You'll notice the modal is created in the #modal-root element, which is a root element alongside the #app-root element. This is a great example of how createPortal() can be used without violating any HTML rules.
<div id="app-root"></div>
<div id="modal-root"></div>

I ran into another use case a few months ago. Because React 16 portals were not available, I had to use a home-baked portal implementation.
I was creating SVG graphs. All of the lines, paths, and so forth needed to be rendered inside an <svg> element. But I wanted to use HTML to render text labels (for a number of reasons). This meant that an object on the graph and its label would necessarily be in separate parts of the DOM. But with portals, I could still keep all of a graph component's logic together. Here's a fictitious example:
const LabeledPoint = ({ x, y, r, labelText }) => [
<circle cx={x} cy={y} r={r} />,
<GraphLabel x={x + 5} y={y}>{labelText}</GraphLabel>,
];
You would use this component inside an <svg> element. The GraphLabel component would use a portal to render labelText in an HTML div element at the same coordinates as that <svg>, using absolute positioning to place it at the correct coordinates.
This way, all of the logic for a single component could be in one place even if I needed to render the actual DOM elements in different places for technical reasons.

Portals is very useful feature when you need to render your component outside the DOM hierarchy of the parent component.
You define a portal using the following syntax:
ReactDOM.createPortal(child, container)
The first argument (child) is any renderable React child, such as an
element, string, or fragment. The second argument (container) is a DOM
element.
See the following tutorial to see how and why to use portals:
https://www.youtube.com/watch?v=lOMU9BeIrO4

Before going into my answer, I'll just note that I interpret the question as "in which cases is there no alternative to using a portal, or a portal would be a demonstrably much better solution?"
There are very few cases where portals are the only solution. A lot of the time there's a way to structure your app so that you don't need to use them. There's some niche use cases, but even there it's usually not the only solution.
For example in the SVG use case, you could instead create a Labels component that takes an SVG React element as argument, and then loops recursively over the children to construct an HTML element with matching labels in the right position. That would as a bonus also make the SVG code a lot simpler. If the SVG is user editable, you'd have to store its state as a whole anyway on each change, allowing you to easily pass the state back into both SVG and label elements. That said, here the portal solution seems at least on par with the alternatives, and could be the simplest in some circumstances.
Dispatching plugin components
Portals can be useful for library/framework authors. It allows plugins to render multiple components in the same element, each of which the framework then portals to a different position in the UI (e.g. editor area, sidebar).
WordPress's block editor uses this for a few things, they call it SlotFill. For example if you're coding a new block in a plugin. You always provide an edit component for each block, which is rendered to the WYSIWYG editor. If it includes an InspectorControls component, everything inside it will go into the sidebar.
The Block Toolbar works in the same way. Content of the <BlockControls/> element is moved to the toolbar that is displayed right above the block content.
This is implemented as a portal to a registered slot.
The advantage of a portal here is that it allows a block's code to reuse the state and hooks in all components, even though they are not rendered in the same place. This makes the process of adding sidebar code very easy and with minimal repetition. If plugins instead needed to provide each of these components as a standalone React component, managing their state would be much more complex.
Example
You won't find ReactDOM.createPortal in the example itself. It's rather an example of how a plugin can benefit from a framework that uses it. See WordPress's source code if you're interested in the implementation details.
I added a simple useState hook to the mentioned InspectorControls example and removed some irrelevant parts.
edit: ( { attributes, setAttributes } ) => {
const [myColor, setMyColor] = useState('#fff');
return (
<div>
<InspectorControls key="setting">
// Simplified HTML, real world blocks use more complex HTML here.
<ColorPalette
value={myColor}
onChange={ setMyColor}
/>
</InspectorControls>
<TextControl
value={ attributes.message }
onChange={ ( val ) => setAttributes( { message: val } ) }
style={ {
backgroundColor: myColor,
color: attributes.text_color,
} }
/>
</div>
);
},

Related

Knockout Google Map: Component vs. Custom Binding Handler

When I google "Knockout Google Maps" I find quite some KO-based Google Maps implementations. All of which I was able to find take the approach to use a custom binding handler whereas I originally intended to implement it as a Knockout component.
Examples:
http://www.codeproject.com/Articles/351298/KnockoutJS-and-Google-Maps-binding
http://www.hoonzis.com/knockoutjs-and-google-maps-binding/
https://github.com/manuel-guilbault/knockout.google.maps
Can anyone point me in the right direction why one would prefer a custom binding handler over a KO component here?
My planned use case is this:
I'm implementing a page with a list of address search results. The list so far is a KO component, each list entry is generated by another KO component which the list component repeatedly calls in a foreach binding. Next to this list of search results I need a google map showing the result entries also in the map. There will also be quite a lot of interaction between the list, the list entries and the map.
Here's what I've got so far:
var GMap = function () {
var self = this;
var initMap = function() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 13,
center: {lat: 51.4387974, lng: 6.9922915}
});
};
initMap();
};
$(document).ready(function() {
ko.components.register('gmap', {
viewModel: GMap,
template: { element: 'gmap' }
});
ko.applyBindings();
});
#map {
height: 400px;
width: 600px;
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.22"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<gmap></gmap>
<template id="gmap">
<div id="map"></div>
</template>
A component and a custom handler are completely different things.
Custom binding
Basically a custom binding have access to:
the HTML component where it's used
the bound value (expression supplied to the binding)
all the other bindings in the element
the binding context of the element, from which you can acces to $root, $parent, and so on
Its definition includes two functions:
init: that allows to do the initial setup, like initializing widgets, setting event handlers and so on
update: it's called after init. In that moment you can access properties (including observable properties) through the binding, all the element bindings, the context and so on. This creates subscriptios that will call update when any of the accessed observable changes.
So a custom binding shuld be used when you need to interact directly with the DOM element, for example to modify its properties, initialize widgets, subscribe to events and so on
Component
A component is completely different. When you define a componente you must define:
a template, which is a set of DOM elements, usually with bindings
a viewmodel (usually a constructor or a factory)
When you use the component:
the viewmodel is instanced
the template is loaded
the viewmodel is bound to the template
So, a componente allows to reuse viewmodels and templates
So, what's the difference?
A custom binding has direct access to the DOM elements, allowing to interact with them, subscribe to events, modify properties, and so on
A component is only a viewmodel, and a set of DOM elements with bindings to that particular viewmodel.
So, in the case of Google Maps, which needs to initialize a widget (the map) and interact with Map events, and respond to observable propèrties cahnges, you could never use a component, because the component doesn't allow the direct interaction with the DOM elements. (Remember is a bunch of HTML elements with bindings, and the corrresponding view model, whic can't include any logic to intercat with those elements).
A custom binding usually applies to a single element (althoug it could handle its children, like foreach). In the case of Google Maps you only need the element in which you'll show the map.
A component is usually a more or less complex set of DOM elements, which are not accesible "from the outside". The only communication with the main viewmodel is done through parameters. The component cannot directly interact with the DOM elements: it must do it via ko bindings.
So, for the case of Google Maps is clear that you need a custom binding.
It only makes sense to create a component when you want to modularize or reuse a set of DOM elements, and the related viewmodel, which can also include functionality like accessing web services (via AJAX), making computations (propbaly by using computed observables), and so on. For example, a shopping cart could be implemented using a component, which would include:
the DOM elements to show the items in the cart (probably an HTML table, and some controls)
controls to modify the cart content (for example for deleting elements, or changing quantities)
a viewmodel that show the total, the taxes and so on
functionality to store the cart for later, or pay for it (which could be ajax calls to services)
In this case the cart would have a viewmodel which would include the computed observables (to show the total and taxes), the functionality to remove items, or modify quantities, or store or pay, and so on. And a concrete set of DOM elements with bindings for this viewmodel, i.e. the HTML to show the cart and interact with it.
In the case of Google Maps a component could not be used without the help of a custom binding or with the hacky use of additional, non ko, scripts.
If you wanted to show a list of places beside a map, and modify that list, you could use a component, which would include a viewmodel with the list and related functionality, and a template including an element with the Google Maps custom binding. That would make sense: viewmodel + several elements.
Conclusion
This all means that a custom binding usually have a deep interaction with the bound DOM element, while a component has a higher level interaction with the elements, which must be done through bindings.
So, they play a role at a very different level. You cannot compare or interchange them.
If you insist on doing so, you could create a beast of a binding which behaves like a component, becasue you have full control on the elements, and full acces to the view model, but that's harder to implement than a component. And probably could do the other way round also in some esoteric way.
Binding
Binding, a custom or not, is a very simple concept that covers 2 things:
A property of a UI element changes, and thus it should update an object (ViewModel)
A property of the object (ViewModel) changes, and thus it should update the UI element.
From the above if only 1 implemented, it is called One Way Binding (because if you change the UI, it will update the object but not the other way around). If both 1 and 2 are implemented, it is called Two Way Binding.
So at any time if you think you need something to do that, you would need to use binding, custom binding if the framework does not have the binding you need.
Most likely, the maps you speak of needed something like above. And it actually did because the author says this in the first paragraph:
Concretely, you can learn how to make the maps marker part of the View and automatically change its position any time when the ViewModel behind changes.
See, the author talks about 2 above: When the ViewModel changes, change the position of UI element.
Component
A component is a concept of having a reusable item that may have a UI but not necessarily, and all the code needed to make it work packaged along with it. This way it can be reused. For example, it may simply be an input UI element that only allows numbers. All the code needed for it is packaged along with the UI element.
Now the code packaged along with it may code related to bindings. It may even have custom bindings if the framework they used did not have the binding they needed. In addition it may have additional code that has nothing to do with binding.
Furthermore, a component may have a single UI element or multiple. A good example of a component with multiple elements would be a message box.
In Conclusion
Bindings and Components are separate things. A component may have bindings within it or it may have other code to make it work or both.
In the case of the maps you speak of, they have only added a feature to it: To react to changes in the ViewModel. It is not a component because it is not self contained and reusable.
They could have done it using a component. However, if they did that and said it is a KO component, it may still have KO specific binding code packaged with it along with the ViewModel and all the UI elements needed.

Polymer understanding attributes

I am relatively new to programming and have been reading up and watching videos on Polymer 1.0. But I am struggling to wrap my head around some of it, I have a general understanding of the elements and have been browsing the catalog. But I am not making certain connections. Such as how an item on a paper-menu element can be accessed by using on-iron-select calling _itemSelected?
how does on-iron-select link to paper-menu, and where is the documentation for this? I have looked trough the catalog and the bower repo I have downloaded and I can't see it.
I event build some basic elements and console logged this.$, even there I do not see this properties and attributes
In order to dive into what's going on, you need to understand Polymer 1.0's Behaviors.
Once that background info is established, the source for the <paper-menu> element will point you in the right direction:
Polymer({
is: 'paper-menu',
behaviors: [
Polymer.IronMenuBehavior
]
});
That Polymer.IronMenuBehavior in turn makes use of its own set of behaviors, including Polymer.IronSelectableBehavior. All those incremental behaviors create the overall functionality that you're seeing in the <paper-menu> element.
The nice thing about this approach is that any other element that also makes use of, e.g., Polymer.IronSelectableBehavior will share the same general properties and methods, and a collection of elements feels like more of a coherent library.

How to handle testing an HTML control that lacks sufficiently unique attributes?

I'm using Coded UI Test to test a web application.
I have a class Locator that I use to stash the specifics needed for CUIT to find a control. To operate on a control, a page object specifies the locator, not the control, and lower-level functions find the control and perform the operation.
Right now, my class has:
Locator name.
One or more attrName/attrValue pairs that can locate the HTML element for the control.
An operator (Contains or EqualTo) that specifies the matching needed.
The problem: Some of the controls I need to operate on don't have enough unique attributes to allow them to be found. (Yes, I know the developers should improve their HTML, but I don't control that.) I have been using a locator to find a nearby element, then "walking" in the DOM to get to the element I want. I hate having this DOM-walking code in my page object, even factored into a function.
A possible solution: I'm considering enhancing class Locator so that it can have either the attrName/attrValue pairs or a reference to a function that has the DOM-walking code. One advantage of this is that the page objects would always use a locator object. Another is that when the HTML is improved, the locator could change from DOM-walking code to attrName/attrValue pairs, which would be transparent to the page object.
Still, I think this may be over-complicated.
Is there a better solution to this problem?
Not sure specifically how your locator works, but could you find the closest parent to that object, let's say an HTML Div with an id of "parent", and then count the tag instances underneath? For example:
HtmlDiv id="parent">
HtmlHyperlink>text1</
HtmlHyperlink>text2</
Would require the following code:
public HtmlHyperlink text2Link
{
get
{
HtmlDiv parentDiv = new HtmlDiv(browser);
parentDiv.SearchProperties["id"] = "parent";
HtmlHyperlink target = new HtmlHyperlink(parentDiv);
target.SearchProperties["TagInstance"] = "2";
}
}
This would find the 2nd hyperlink under the parent object. (Tag instances are not zero based).
Then, you'd just interact with your object as needed:
Mouse.Click(text2Link);
for example.

How can I automate test HTML5 elements in the UIAWebView in Instrument?

I am trying to automate the test of a mobile app, which is HTML5 embedded in Native app frame. I used the following code to get the elements in Instrument
UIALogger.logStart("Log elements in the landing page");
UIATarget.localTarget().logElementTree();
UIALogger.logPass("done");
And it will show the HTML5 component as UIAWebView. But for example, if there is a link in the HTML, and I want to click, I can only know it by the position. Is there any method that I can call to get the tags in HTML5?
Thanks a lot!
There is no such menthod, you will get elements with target.logElementTree(); as you used. If elements are native elements, you can use them with predefined methods like buttons() or links() else you will have to use them specifying position (xy coordinates) only. This problem always exists with Hybrid apps.

Building HtmlElement object trees

I'm using the MSIE WebBrowser control in a C# desktop application and am looking for a way to build and maintain trees of HtmlElement objects outside of this control. I am trying to quickly switch between multiple complex pages without incurring the overhead of re-parsing the HTML each time (and I don't want to maintain multiple controls that are shown/hidden as needed).
I discovered that a) I can only create HtmlElement objects via the control's HtmlDocument and b) once I remove a "trunk" of HtmlElement objects from the control's HtmlDocument, it "dies off," even though I keep maintaining a strong reference to the root element.
How can I do this?
P.S. I am willing to consider alternative browser controls (e.g. Gecko) if they allow me to accomplish the above.
This will do it
// On screen webbrowser control
webBrowserControl.Navigate("about:blank");
webBrowserControl.Document.Write("<div id=\"div1\">This will change</div>");
var elementToReplace = webBrowserControl.Document.GetElementById("div1");
var nodeToReplace = elementToReplace.DomElement as mshtml.IHTMLDOMNode;
// In memory webbrowser control to load fragement into
// It needs this base object as it is a COM control
var webBrowserFragement = new WebBrowser();
webBrowserFragement.Navigate("about:blank");
webBrowserFragement.Document.Write("<div id=\"div1\">Hello World!</div>");
var elementReplacement = webBrowserFragement.Document.GetElementById("div1");
var nodeReplacement = elementReplacement.DomElement as mshtml.IHTMLDOMNode;
// The magic happens here!
nodeToReplace.replaceNode(nodeReplacement);
I doubt this will improve performce as the text renderer is fast, and the memory consumed will still be the same if you have one large page with hidden div's or have multiple div's in memory in other objects?
You can use the MSHTML library (mshtml.dll) to achieve this. Basically you would use a single about:blank page and then dynamically write and remove content from it.
See this blog post on this subject
You can also write a custom interface wrapper that exposes the functionality you need from mshtml rather than referencing the whole thing (Nearly 8MB) and it is really easy to do using f12 in VS.
Do you really need to remove them enturely? How about leaving your "branch" in the DOM as the child of a DIV whose style="display:none". That way they're real, live DOM objects but not visible.
I think you could also use the htmlagilitypack
It allows you to parse once, querying the HTML tree using XPath or via iterators and re-writing the tree with a save method when done.
Depending on your structure, you might just create an adapter around the classes, because it only works on an entire html document and you want it on elements only, but this should be not too hard.