How to get value when React wraps content in spans? - reactjs

I have a React component that renders some html like below, with one callback method (this.deleteItem) triggered upon click of an x. In the callback method, I try to get the content associated with each of the two refs like this
var date = this.refs.date.getDomNode.value;
var content = this.refs.content.getDomNode.value;
but the result is undefined in both cases. When I simply do this.refs.content.getDomNode (instead of looking for the value) it shows me a div with some span tags inside, and inside of one of those is the content I was seeking. Similarily with the date ref, it is a <small></small> element with spans inside.
Question: how to get the value/content from a div or element when react wraps content in spans?
<div ref="wrapperdiv">
<span className="delete" onClick={this.deleteItem}>x</span>
<small ref="date"> {date} </small>
<div ref="content"> {content } </div>
</div>

This is a known limitation of react, in that it wraps any floating text nodes in a span because it has to handle the data-reactid of the component. See this question too.
Perhaps if you tried to remove the white space around the content?
<div ref="wrapperdiv">
<span className="delete" onClick={this.deleteItem}>x</span>
<small ref="date">{date}</small>
<div ref="content">{content}</div>
</div>

Also try:
this.refs.content.getDomNode().children[0].textContent
to get the value of the span. (Not sure if there is a react specific function for this). This will have to be done as well as removal of the white space within:
<small ref="date">{date}</small>
<div ref="content">{content}</div>
This is important because react generates span tags to handle the data-reactid. Take a look at: Rid of repeated spans in React.js?.

Related

Angular show-hide flickers

I'm switching the visibility of 2 elements when clicking them. A very simple use case:
<div ng-hide="filtersOpened"
ng-click="filtersOpened=true">
filters (opened)
</div>
<div ng-show="filtersOpened"
ng-click="filtersOpened=false">
filters (closed)
</div>
The change happens, but it flickers so that for a very short moment I see both elements together.
How can I make the change behave nicer, smoother, without the flickering? I've read about ng-cloack but doesn't seem like it's related since I'm not using a template.
Maybe try ng-if instead:
<div ng-if="filtersOpened" ng-click="filtersOpened=true">
filters (opened)
</div>
<div ng-if="!filtersOpened" ng-click="filtersOpened=false">
filters (closed)
</div>

Expanding tiles layout using Angular in responsive layout

I'm developing an Angular single-page app with a responsive layout. The current page I'm working on uses a tile-based layout that auto wraps extra tiles to the next row. The HTML is below and, in the responsive layout, it can show 1, 2, or 3 tiles per row depending on the width of the row (it positions them using floats).
<div class="tiled_panel">
<div class="tile_1">...</div>
<div class="tile_2">...</div>
<div class="tile_3">...</div>
<div class="tile_4">...</div>
<div class="tile_5">...</div>
...
</div>
Now each tile will be given a "Learn More" button. The design calls for a block to expand between the row of the selected tile and the row below. This block will be the full width of the row and will be closed when the user closes it or clicks on a different Learn More button.
My first thought was to arrange the HTML as below using ng-if to hide or display the expander divs but I can't figure out the CSS needed to have it display between the rows.
<div class="tiled_panel">
<div class="tile_1">...</div>
<div class="expander_1">...</div>
<div class="tile_2">...</div>
<div class="expander_2">...</div>
<div class="tile_3">...</div>
<div class="expander_3">...</div>
<div class="tile_4">...</div>
<div class="expander_4">...</div>
<div class="tile_5">...</div>
<div class="expander_5">...</div>
...
</div>
My second thought, since I'm using Angular, was to somehow use transcluding or including to insert the relevant HTML into the appropriate spot. Again, I can't figure out how to identify where I need to insert the HTML?
I've tried searching around for other people's solutions to similar problems since I figured its not that unusual a requirement but I haven't yet been able to find anyone else who is doing this.
Can anyone else suggest what I need to do to identify the where to insert the HTML or how to generate the CSS? Or even suggest another solution that I haven't considered yet?
Although I have 70% understand of what you mean, I think ng-class can simply solve what you've faced. The solution code is like below. And I setup jsfiddle.
Html looks like this.
<div ng-app="" ng-controller="MyCtrl">
<div class="tiled_panel">
<div>Tile 1 <a href ng-click="change_tile(1)">More</a></div>
<div class="expander" ng-class="{'close': opentile===1}">Expander 1<a href ng-click="change_tile(-1)">Close</a></div>
<div>Tile 2 <a href ng-click="change_tile(2)">More</a></div>
<div class="expander" ng-class="{'close': opentile===2}">Expander 2<a href ng-click="change_tile(-2)">Close</a></div>
</div>
</div>
Your controller code looks like this.
$scope.change_tile = function(value){
$scope.opentile = value;
}
$scope.change_tile(0);
Css looks like this.
.expander{
visibility: hidden
}
.close{
visibility: visible
}

Nested Element binding in Angular

I'm running into an issue where I want to display a title label such that there is (i) A primary title which appears as an h1 element and (ii) A sublabel within the h1 element but enclosed in the tag
Doing this works:
<div id="banner">
<h1>
{{rootLabel}}
<span><small>{{rootSubLabel}}</small></span>
</h1>
</div>
My issue with that code though is that the brackets and names for rootLabel and rootSubLabel are visible in the browser until angular properly reads them.
I've found that I can mask that issue by using Angulars ng-bind instead:
<div id="banner">
<h1 ng-bind="rootLabel">
<span><small ng-bind="rootSubLabel"></small></span>
</h1>
</div>
Unfortunately the second bind doesn't get rendered by Angular though.
What I'm wondering is how would something like this be done properly in Angular?
This is because
<h1 ng-bind="rootLabel">
<span><small ng-bind="rootSubLabel"></small></span>
</h1>
will replace everything inside the h1 with {{rootLabel}}
The correct way to use ng-bind in this case should be
<h1>
<span ng-bind="rootLabel"></span>
<span><small ng-bind="rootSubLabel"></small></span>
</h1>

How to write a directive which can render some html code with angular directives, and show it as text?

I think some sample code can explain my purpose.
Some html code with angular:
<div ng-init="buttons=['add','edit','delete']">
<div show-result-as-text>
<button ng-repeat="button in buttons">{{button}}</button>
</div>
</div>
You can see there is a custom directive "show-result-as-text" which I want to define. It should render the inner html code with angular directives, then show them as text.
The final html should be:
<div ng-init="buttons=['add','edit','delete']">
<div show-result-as-text>
<button>add</button>
<button>edit</button>
<button>delete</button>
</div>
</div>
And when the buttons value changes, the escaped html should also be changed.
I've tried to write one myself, but failed after 2 hours of work.
UPDATE
A live demo: http://plnkr.co/edit/fpqeTJefd6ZwVFEbB1cw
The closest thing I could think of is exemplified here: http://jsfiddle.net/bmleite/5tRzM/
Basically it consists in hiding the src element and append a new element that will contain the outerHTML of each src child.
Note: I don't like the solution but it works, so I decided to share it...

In CSS, is ".class1.class2" legal and common usage?

I am quite used to seeing
div.class1
and
#someId.class1
but what about
.class1.class2
? And I think it is identical to
.class2.class1
? Because there was an element with id someId but now we have two elements of this type showing on the page, so I want to add a class and use the class instead of id, therefore the .class1.class2 instead of #someId.class1
It will select items with both classes. So not items with either one.
<span class="class1 class2"></span>
Yes, it is both legal and common. In the element, you would have something like this:
<div class="class1 class2">Hello</div>
It's nice for syntactic styling. To give you an example, let's say you have the following html:
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
You can add a second (and third, forth, etc.) class that modifies "box". For example:
<div class="first odd box">
</div>
<div class="second even box">
</div>
<div class="third odd box">
</div>
<div class="fourth even box">
</div>
Then, in styling, to style different box groups, you can do the following:
.odd.box {
}
.first.box, .fourth.box {
}
.first.box, .even.box {
}
This will be interpreted by the browser if you give your element does two class:
.class1.class2{width:500px;height:300px;}
<div class="class1 class2"> </div>
If you do like this, it will not be interpreted, resulting on a div with no styles:
.class1.class2{width:500px;height:300px;}
<div class="class2"> </div>
This will be interpreted (resulting on an element with a dimension of 500px X 300px:
.class1 {width:500px;}
.class2 {height:300px;}
<div class="class1 class2"> </div>
The common use of css, is to tell the browser that a certain element with and ID or CLASS of a certain name will get a set of styles, or tell the browser that a certain ID or CLASS will get a set of Styles, like so:
Ex 1:
.class1 {width:500px;} -> elements
with this class will get 500px of
width.
Ex 2:
div.class1 {width:500px;}
-> only a
div element with this class will get
500px of width.
Ex 3:
div.class1, h1.class1 {width:500px;}
-> only a div and a h1 element with this class will get 500px of width.
You can read valid information about css at:
W3C CSS SYNTAX PAGE
Just wanted to confirm the answer given by Jouke van der Maas,
which is the right answer. I would like to quote the following
excerpt from the CSS 2.1 specification:
5.2 Selector syntax
A simple selector is either a type selector or universal selector
followed immediately by zero or more attribute selectors, ID
selectors, or pseudo-classes, in any order. The simple selector
matches if all of its components match. [snip]
Since the .classname selector is equivalent to the [class="classname"] selector,
it is an attribute selector. Note the "in any order" bit. Hence the selector
.class1.class2
is identical to the selector
.class1.class2
and matches both elements like
<span class="class1 class2">Hello World</span>
as well as
<span class="class2 class1">Hello World</span>
which is the same thing, as well as
<span class="class1 class2 class3">Hello World</span>
etc...
You can also get even more fancy.

Resources