Issues with text rendering in react component - json

So I am working with an API, and found this in the documentation:
let message = {
"text" : "<i>or</i> HN: the Next Iteration<p>I get the impression that with Arc being released a lot of people who never had time for HN before are suddenly dropping in more often. (PG: what are the numbers on this? I'm envisioning a spike.)<p>Not to say that isn't great, but I'm wary of Diggification. Between links comparing programming to sex and a flurry of gratuitous, ostentatious adjectives in the headlines it's a bit concerning.<p>80% of the stuff that makes the front page is still pretty awesome, but what's in place to keep the signal/noise ratio high? Does the HN model still work as the community scales? What's in store for (++ HN)?",
"time" : 1203647620
}
So in react (using function component), what is the proper way of rendering message.text? I am asking because my rendering output still has the tag <i></i> and <p></p> in the text when I return {message.text}. So I guess there is something wrong.

If you want to render a string containing html you can use dangerouslySetInnerHTML
In your case will be:
<div dangerouslySetInnerHTML={{ __html: message.text }} />
Watch out using this attribute because it could expose your app to XSS attacks. (check https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml)

Related

How to get a I18n variable value I can return to my Angular parent component?

I'm new to Angular and I just put in place an i18n (2 languages) system for a website I am creating. Everything works properly but in order to switch from one language to another in my header, I feel stuck.
I followed the Angular documentation to transfer my variables from child to parent component and I ended with this:
<input type="text" id="item-input" #lang>
<button type="button" (click)="changeChosenLang(lang.value)">
{{ 'global.lang' | translate }}
</button>
As you can see, I write my language in the input form and I send it to the proper component with a button. What I wanted was to click on my 'global.lang' text and to be able to send its value to the parent component, since the value is the language which is not actually used.
I don't know how to put my 'global.lang' text in a variable, neither what kind of balise I can use. Also I didn't know how to summarize my problem to search for it on StackOverflow so if you know a similar post, don't hesitate to post the link.
Thank you for your reading!
I found a less tortured way (poor brain) to have the result I wanted:
<span (click)="changeChosenLang()">
{{ 'global.lang' | translate }}
</span>
First I temporary changed my button to a span balise and I deleted the parameter from my changeChosenLang() function. Then, I transferred a variable 'lang' from my parent component to this one, witch contains the value of the language chosen in my app constructor. At each click, I change its value in my changeChosenLang() function and everything works great!
I hope it can help someone someday. The moral of this post is: the simpler, the better! Have a good day.

Vue: Chrome tab crashes when trying to display a long string

I have a vue component whose purpose is to display a string.
The string can be very long - the one I tested had about 3 megabytes.
When trying to display string of such size the chrome tab crashes with its CPU usage going up to 100%. The console is clear.
Here's the simplified code of the component:
<template>
<div>
{{ output }}
</div>
</template>
<script>
export default {
name: "OutputField",
props: ['output']
}
</script>
The problem does not occur on Firefox.
It also disappears once the {{ output }} is commented out - which leads me to believe it has nothing to do with the logic of parent component.
Last but not least, when directly inserting the string into the innerHTML of the div, it is shown correctly even on Chrome.
I would really appreciate an explanation of this behavior and suggestions on how to display the string in a way that won't lead to it. Thanks in advance!
After looking into the problem more I managed to narrow down the possible cause to specific string messing up Vuetify's behavior in Chrome.
Created a separate question, as adding the details here would make the initial one hard to read.
It is available here: ­ inserted into string in Vuetify crashing Chrome tab
Since the only purpose of your component is to display a value passed as a prop, you should use a functional component. It basically is a component that gets rid of the overhead that vue needs to have a state (data, methods, etc.). Instead, it will deal only with props passed to it.
You can set it up like this:
ChildComponent.vue
<template functional>
<div>{{ props.outputVal }}</div>
</template>
ParentComponent.vue
<ChildComponent outputVal="stringToDisplay">
It probably won't make the page respond instantly still, as that's a lot of data to display, but it should increase the performance by a lot and at least allow the string to display.
Here is an example of it which displays a huge string:
https://codesandbox.io/s/vue-functional-components-xbpci

MVC Sitemap renders empty when the current action is not in the Mvc.sitemap file

Is it possible to force the sitemap control to render the menu when the current action is not listed in the MVC.sitemap file?
I have a simple top nav. When the current action is in the sitemap, the call to .Menu() will render the correct <ul><li>.. data. However, if I got to a page that is not in the sitemap such as /Home/Login, then it will not render any html at all (not even a comment, just empty space). This isn't an [authorize] issue; the menu is fine when i'm in '/Home/Index'.
It seems like it should render what was requested, but just not set the IsCurrentNode and IsNodeInPath properties. Here is the call I am making
<div id="main-nav">
#Html.MvcSiteMap().Menu(0, true, true, 1)
</div>
The Mvc.sitemap file:
<mvcSiteMapNode title="Home" controller="Home" action="Index">
<mvcSiteMapNode title="Form New Human" controller="Person" action="Create"/>
<!-- there is no mvcSiteMapNode for "Home" "Login" -->
</mvcSiteMapNode>
Found the way around it. It apparently isn't a built in extension method, or at least I couldn't find one. You could call Html.MvcSitemap().Menu(Html.MvcSiteMap.Provider.RootNode,...) but I didn't want to instantiate the helper twice.
<div id="main-nav">
#{
var sm = Html.MvcSiteMap();
#sm.Menu(sm.Provider.RootNode, true, true, 2); // 2 levels (home, plus main nav)
}
</div>
Looking around in the disassembly seems to show that it works a little like this:
You really need a starting node
If you don't give it one, it tries to find one based on the current node
plus restrictions (forward searching, depth restrictions, etc)
if you want nodes from level 1, you have to know what level you are on
Since that returns null, starting node is null, which means the helper writes an empty string
There may be a combination of tricks, or an overload or two, which can be finagled into doing this, but I can't find it right now. This works for my needs (simple top menu). There has to be a simpler way to do this, something with wild cards, or route based, with a closest match thing going on. I figured menus were a fairly standard part of a web app, and this would be covered :)

shrink html help

I have an array of 2000 items, that I need to display in html - each of the items is placed into a div. Now each of the items can have 6 links to click on for further action. Here is how a single item currently looks:
<div class='b'>
<div class='r'>
<span id='l1' onclick='doSomething(itemId, linkId);'>1</span>
<span id='l2' onclick='doSomething(itemId, linkId);'>2</span>
<span id='l3' onclick='doSomething(itemId, linkId);'>3</span>
<span id='l4' onclick='doSomething(itemId, linkId);'>4</span>
<span id='l5' onclick='doSomething(itemId, linkId);'>5</span>
<span id='l6' onclick='doSomething(itemId, linkId);'>6</span>
</div>
<div class='c'>
some item text
</div>
</div>
Now the problem is with the performance. I am using innerHTML to set the items into a master div on the page. The more html my "single item" contains the longer the DOM takes to add it. I am now trying to reduce the HTML to make it small as possible. Is there a way to render the span's differently without me having to use a single span for each of them? Maybe using jQuery?
First thing you should be doing is attaching the onclick event to the DIV via jQuery or some other framework and let it bubble down so that you can use doSomething to cover all cases and depending on which element you clicked on, you could extract the item ID and link ID. Also do the spans really need IDs? I don't know based on your sample code. Also, maybe instead of loading the link and item IDs on page load, get them via AJAX on a as you need them basis.
My two cents while eating salad for lunch,
nickyt
Update off the top of my head for vikasde . Syntax of this might not be entirely correct. I'm on lunch break.
$(".b").bind( // the class of your div, use an ID , e.g. #someID if you have more than one element with class b
"click",
function(e) { // e is the event object
// do something with $(e.target), like check if it's one of your links and then do something with it.
}
);
If you set the InnerHtml property of a node, the DOM has to interpret your HTML text and convert it into nodes. Essentially, you're running a language interpreter here. More text, more processing time. I suspect (but am not sure) that it would be faster to create actual DOM element nodes, with all requisite nesting of contents, and hook those to the containing node. Your "InnerHTML" solution is doing the same thing under the covers but also the additional work of making sense of your text.
I also second the suggestion of someone else who said it might be more economical to build all this content on the server rather than in the client via JS.
Finally, I think you can eliminate much of the content of your spans. You don't need an ID, you don't need arguments in your onclick(). Call a JS function which will figure out which node it's called from, go up one node to find the containing div and perhaps loop down the contained nodes and/or look at the text to figure out which item within a div it should be responding to. You can make the onclick handler do a whole lot of work - this work only gets done once, at mouse click time, and will not be multiplied by 2000x something. It will not take a perceptible amount of user time.
John Resig wrote a blog on documentDragments http://ejohn.org/blog/dom-documentfragments/
My suggestion is to create a documentDragment for each row and append that to the DOM as you create it. A timeout wrapping each appendChild may help if there is any hanging from the browser
function addRow(row) {
var fragment = document.createDocumentFragment();
var div = document.createElement('div');
div.addAttribute('class', 'b');
fragment.appendChild(div);
div.innerHtml = "<div>what ever you want in each row</div>";
// setting a timeout of zero will allow the browser to intersperse the action of attaching to the dom with other things so that the delay isn't so noticable
window.setTimeout(function() {
document.body.appendChild(div);
}, 0);
};
hope that helps
One other problem is that there's too much stuff on the page for your browser to handle gracefully. I'm not sure if the page's design permits this, but how about putting those 2000 lines into a DIV with a fixed size and overflow: auto so the user gets a scrollable window in the page?
It's not what I'd prefer as a user, but if it fixes the cursor weirdness it might be an acceptable workaround.
Yet Another Solution
...to the "too much stuff on the page" problem:
(please let me know when you get sick and tired of these suggestions!)
If you have the option of using an embedded object, say a Java Applet (my personal preference but most people won't touch it) or JavaFX or Flash or Silverlight or...
then you could display all that funky data in that technology, embedded into your browser page. The contents of the page wouldn't be any of the browser's business and hence it wouldn't choke up on you.
Apart from the load time for Java or whatever, this could be transparent and invisible to the user, i.e. it's (almost) possible to do this so the text appears to be displayed on the page just as if it were directly in the HTML.

GWT Widget from HTML

I have a block of HTML that I would like to use as the basis of a GWT widget, but am not quite sure the best way to do so. As an example, my HTML block looks something like this:
<div class="my-widget">
<div class="header">
<span class="title">Title Text</span>
</div>
<div class="body">
<span class="content">Content Text</span>
</div>
</div>
Now, I can of course paste this as a static string into an HTML widget, but in this case I need the ability to set the text of the "title" and "content" elements on the fly. This kills (or at least makes significantly more difficult) the static text option.
The first thing that comes to mind in that case is to build out the elements in GWT manually and hold references to the ones I need to alter, like so:
DivElement container = document.createDivElement();
setStyleName(container, "my-widget");
setElement(container);
DivElement header = document.createDivElement();
setStyleName(header, "header");
container.appendChild(header);
// Hold onto this element for later manipulation
DivElement title = document.createDivElement();
setStyleName(title, "title");
header.appendChild(title);
But this quickly get unmanageable for all but the simplest of layouts (which mine is not.)
What I would like is the ability to send the HTML in as static text and then do some sort of selector, like jQuery, to query the elements I want to manipulate. I'm aware of GWT-Query but I haven't been able to get it to run without error, and it seems to me to be a bit too early in it's lifespan for me to be comfortable integrating it into a professional product just yet.
I'm also aware of Google's UiBinder, which sounds exactly like what I want. The problem there is, as far as I can tell, that functionality is only available in GWT 2.0, which is still in a release candidate state and therefore unusable for me.
So, given all that (sorry for the long question!) do you have any suggestions about how best to achieve something like this?
GWT 2.0 will be out before the end of the year. So unless you need to deliver in a few days time, I would start working with the RC2 and try out the new UIBinder approach.
How about using HTML.wrap(). For example, if you added an id of "my-widget" to your outer-most div you could then do something like:
HTML myWidget = HTML.wrap(RootPanel.get("my-widget").getElement());
You can use the InlineHTML widget to produce a span and control its content.
As you probably know, GWT doesn't provide a built in widget that maps directly to a span element. If you can use a div for the title and content, then this bit of code should (no GWT on this machine, going a bit by memory) generate the DOM structure you have.
FlowPanel myWidget = new FlowPanel();
myWidget.setStyleName("my-widget");
SimplePanel header = new SimplePanel();
header.setStyleName("header");
Label title = new Label(titleText);
title.setStyleName("title");
header.add(title);
myWidget.add(header);
SimplePanel body = new SimplePanel();
body.setStyleName("body");
Label content = new Label(contentText);
content.setStyleName("content");
body.add(content);
myWidget.add(body);
From here, you can provide accessors to the content and title labels and update them as needed.
title.setText(newTitle);
content.setText(newContent);
The same as above, but getting a GWT Panel (be able to append childs). This is also useful when you need to wrapp a 3rd party toolkit GUI object as a GWT widget:
Panel gwtPanel = HTMLPanel.wrap(anElement);
The following code suites for me:
HorizontalPanel divContainer = new HorizontalPanel ();
Element div = DOM.createDiv();
div.appendChild(...); // whatever element it could fit inside
divContainer.getElement().appendChild(div);
Edit
The idea behind this is manipulating the DOM with the other widgets you have already programmed.
PS: I'm using GWT 2.4