React: microdata typeScope being pased weirdly - reactjs

I'm trying to set microdata to a p element contained in a parent component. When I set itemScope="" in the parent I don't get it in the p element in the dom, but if I set itemScope alone, it works as expected, although this means itemScope={true} as per React rules. ItemScope is a boolean attribute so as per HTML specs it should be empty string or canonical value when you want it to be considered true. What am I missing?
See fiddle:
https://jsfiddle.net/rv9085ob/
<!-- html -->
<div id="app"></div>
// js
const SimpleComp = (props) => <p {...props}>ItemScope is [{JSON.stringify(props.itemScope)}]</p>;
const fragment = <div>
<SimpleComp itemScope="" />
<SimpleComp itemScope />
<SimpleComp itemScope={true} />
</div>;
ReactDOM.render(fragment, document.querySelector("#app"))
Results in:
<div>
<p>ItemScope is [""]</p>
<p itemscope="">ItemScope is [true]</p>
<p itemscope="">ItemScope is [true]</p>
</div>

Please refer to this issue in the React Github repository. https://github.com/facebook/react/issues/13400
There is a PR open for this here, it seems to be ongoing - https://github.com/facebook/react/pull/13404

Related

Props vs Children to pass HTML content in ReactJS

I need create a component to render like this:
<div class="row">
<div class="col">
<div class="some another class">
<h3>{{title}}</title>
</div>
</div>
<div class="col">
<p>{{contentA}}</p>
</div>
<div class="row">
<div class="some wrapper">
<p>{{contentB}}</p>
<div>
</div>
<div>
It will receive the following data:
title - a string
contentA - a large string (paragraph), may contain
links (a href)
contentB - a large string or a complex HTML code
Here are the following methods I found. However, I'm not sure about which one is the recommended way by React.
Method 1
<Component title="a" contentA="some large content" contentB="another large content"/>
Pros: Easy to access different props in different sections of the component
Cons: Too complex to handle if the content as large HTML content
Method 2
<Component>
<title>a</title
<content>some large content</content>
<content>another large content</content>
</Component>
Pros: Much simpler code
Cons: Need to filter props.children and find each element to put in correct place in the component
This is not really an accurate statement:
Cons: Too complex to handle if the content as HTML contents
If a value can be held in a variable as a string, it can be used as an argument passed into your component. If you don't want to be bothered trying to escape the quotes inside your prop values, I would encourage you to ditch the <Component attr="someValue"/> syntax and instead use <Component attr={'someValue'}/>. This allows you to pass variables into your props. This also allows you to use template literals to pass values, like so:
<Component
title="a"
contentA={`
<html>
<head></head>
<body>
<p>Here is my super-big</p>
<p>HTML-infused content</p>
<p>I can even inject ${variables} in here!</p>
</body>
</html>
`}
contentB="another large content"
/>
If you feel like that starts to clutter-up the declaration of your component, you can instead set those values in a variable and then pass them very cleanly into the component, as such:
render() {
const bigHtmlContent = (
<html>
<head></head>
<body>
<p>Here is my super-big</p>
<p>HTML-infused content</p>
<p>I can even inject {variables} in here!</p>
</body>
</html>
);
return (
<Component
title="a"
contentA={bigHtmlContent}
contentB="another large content"
/>
);
}
Of course, you can move the definition out of the render() function altogether if that suits you better:
getBigHtmlContent() {
return (
<html>
<head></head>
<body>
<p>Here is my super-big</p>
<p>HTML-infused content</p>
<p>I can even inject {variables} in here!</p>
</body>
</html>
);
}
render() {
return (
<Component
title="a"
contentA={() => this.getBigHtmlContent()}
contentB="another large content"
/>
);
}
When I'm creating components, I tend to pass everything as props (as shown in the examples above). I only use children if I'm creating a higher-order component which, by design, is supposed to act as a container for certain types of children.
For example, in Material UI there is a <List> component which requires one-or-more <ListItem>s. In that case, I don't think it would make much sense to pass the <ListItems>s as props. They are (and should be) children of the <List> component.
React is all about creating granular components, the more granular you component tree is, you are doing it the more React way.
You say you get 3 things text,contentA and ContentB
Title: it's already granular.
content A: You say its a "a large string (paragraph), may container links (a href)"
, if its a paragraph it is granular but if its a collection of paragraphs, I think you should take that to a different component. Ex: ContentA component
Content B: This is clearly said that its a complex HTML code, that is what is React for, you need to break this complex HTML code into granular components which will make it more maintainable and it is a React best practice too.
have patience while breaking this into components, it's definitely worth it.
hope that helps.

React: no <span> around text nodes

According to React 15.0 release notes, React is no longer supposed to emit <span> tags around text nodes. I tried that using jsbin and script
const Span = () => (<span>a</span>)
const text = 'text'
const Text = () => (<span>{text}</span>)
const Div = (<div>
<Span/><Span/><Span/><Text/>
</div>)
ReactDOM.render(Div, document.querySelector('#target'))
is rendered as
<div data-reactroot="">
<span>a</span>
<span>a</span>
<span>a</span>
<span>text</span>
</div>
So it doesn't work. I'd expect string a to be rendered without surrounding <span> tags. How is this feature supposed to work? Is it necessary to enable it in some way?
The feature is used when writing something like this:
<div>{'a'}{'b'}</div>
"a" and "b" was surrounded by tags and the dom was kinda full with this tags when using this multiple times in different components.
With 0.14.8 this was rendered as:
<div data-reactid=".0">
<span data-reactid=".0.0">a</span>
<span data-reactid=".0.1">b</span>
</div>
With 15.0 this is rendered as:
<div data-reactroot>
<!-- react-text: 2 -->a<!-- /react-text -->
<!-- react-text: 3 -->b<!-- /react-text -->
</div>
This is explained in https://github.com/facebook/react/pull/5753 and can be tested with something like https://codesandbox.io/s/N1znXxXL.

AngularJS ng-show 2 way binding not working

I am new to AngularJS and I have seen others asking similar questions, but the answers are not working for me. Rather than hijacking those questions, I thought I would open one for myself.
I am creating a demo app -- it lists "sites" which can be added to or deleted. I am using the ng-show attribute to display the required html div while hiding the others.
Here is the back-end javascript--
var SiteMaintenanceModule = angular.module("SitesMaintenance", []);
SiteMaintenanceModule.controller("siteCtrl", diveSiteCtrlfn);
function diveSiteCtrlfn($scope) {
// initializing the sites array
$scope.sites = sites;
//initializing the Divs array
$scope.allowedDivs = ["listSiteDiv","addSiteDiv", "editSiteDiv","deleteSiteDiv"];
// setting the first div as selected. This should show the div which lists the sites
$scope.selectedDiv = $scope.allowedDivs[0];
// function to be called with the selected div is to be changed
$scope.setSelectedDiv = function ($divSelectedByUser) {
$scope.selectedDiv = $divSelectedByUser;
}
};
And here is the html
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="SitesMaintenance">
<head>
<title>List of Dive Sites</title>
<link rel="Stylesheet" href="./../zHelpers/bootstrap/css/bootstrap.css" />
<script src="./../zHelpers/angular.min.js"></script>
<script src="./sites.js"></script>
<script src="./SiteMaintenance.js"></script>
</head>
<body ng-controller="siteCtrl">
<!-- Display the list of sites based on the selectedDiv variable-->
<div id="SiteList" ng-show="{{selectedDiv == 'listSiteDiv'}}">
<h3>List of Sites</h3>
<ul ng-repeat="site in sites" ng-model="sites">
<li>{{site.site}} in {{site.location}}</li>
</ul>
</div>
<!-- Display the add site Div based on the selectedDiv variable-->
<div id="AddSite" ng-show="{{selectedDiv == 'addSiteDiv'}}">
<h3>Add New Site</h3>
<div style="display:block; margin:10px">Site: <input id="inputAddSiteName" /></div>
<div style="display:block; margin:10px">Location: <input id="inputAddSiteLocation" /></div>
</div>
<!-- Display the edit site Div based on the selectedDiv variable -->
<div id="EditSites" ng-show="{{selectedDiv == 'editSiteDiv'}}" style="display:block;margin:20px">
Site Name:<input id="InputEditSiteName" />
Site Location:<input id="InputEditSiteLocation" />
</div>
<div id="controls">
<button id="AddNewSiteButton" ng-click="setSelectedDiv('addSiteDiv')">Add Site</button>
<button id="DeleteSiteButton" ng-click="setSelectedDiv('deleteSiteDiv')">Delete Site</button>
<button id="EditSiteButton" ng-click="setSelectedDiv('editSiteDiv')">Edit Site</button>
</div>
</body>
I can set the visible div to whatever I want at the start, by changing the index in the statement "$scope.selectedDiv = $scope.allowedDivs[0];" in the JavaScript.
I change the value of $scope.selectedDiv when any of the buttons on the page are clicked, so as to change the visibility of the divs.
However, the visibility of the divs doesn't change, no matter what the value of $scope.selectedDiv is. In fact, when debugging in chrome, I see that the attribute value of ng-show for each of my divs updates dynamically to "true" or "false" and expected, but the div is still displayed -- the initially invisible divs seems to have a class="ng-hide" attribute, which never changes.
I have tried $scope.$apply() in the JavaScript but that gives errors. Any help would be greatly appreciated.
You don't need to use {{}} interpolation inside ng-show directive directive, it evaluates the expression inside a $scope of your controller directly.
ng-show="selectedDiv == 'addSiteDiv'"
ng-show="selectedDiv == 'listSiteDiv'"
ng-show="selectedDiv == 'editSiteDiv'"

Why does React strangely render the <p> (paragraph) tag?

React is doing strange things with the <p> tag. Using the same markup structure, with a <p> tag vs a <div> tag produces very different results. For example,
var withP = (
<p>
withP
<div />
</p>
);
var withDiv = (
<div>
withDiv
<div />
</div>
);
Here is what the generated markup looks like in chrome:
Here is a live jsbin demo.
Why does React render <p> differently than <div>?
<p> can not have nested block elements. Chrome (not React) is transforming the markup to make it valid.

In Angular.js, is it possible to replace an ng-switch directive element with its contents?

I'm using a switch to conditionally include different content. I want the inner content (e.g. welcome directive) to replace the parent ng-switch element. I know that you can do this with custom directives using the replace=true configuration property, but is this possible to do with built in directives such as ng-switch?
<div id="container">
<ng-switch on="tabIndex">
<welcome ng-switch-when="welcome"></welcome>
<main ng-switch-when="main"></main>
<help ng-switch-when="help"></help>
</ng-switch>
</div>
For example, When the value of tabIndex is 'help', I want the following html to result:
<div id="container">
<help><!-- contents of help template --></help>
</div>
You'll always need the logic there, but you don't have to use an element for a switch. It'll work just as well as an attribute on the parent:
<div id="container" ng-switch on="tabIndex">
<welcome ng-switch-when="welcome"></welcome>
<main ng-switch-when="main"></main>
<help ng-switch-when="help"></help>
</div>

Resources