Component selector in variable - Angular 2 - html

I have written my own table module. Calling it in HTML code looks like this:
<my-table [data]="variableWithArr"></my-table>
Now, pretty nice table is being displayed. Cool. But what if I want to have a progress bar in some column of table? I thought that I could put a HTML code with component selector as value, for example bootstrap progressBar, like this:
for(let record of variableWithArr) {
record[0] = '<ngb-progressbar type="danger" [value]="100"></ngb-progressbar>';
}
Unfortunatelly, Angular displays only a HTML code but dooes not interpret it as component selector, so I receive something like that in DOM:
<td><ngb-progressbar type="danger" [value]="100"></ngb-progressbar></td>
How to fix it?

This is not how Angular works - you can't insert arbitrary HTML (innerHTML or otherwise) and expect that directives will be picked up & applied. Making Angular work this way would require shipping entire compiler to a browser and would defeat the whole purpose of all the great optimizations that can be done with the ahead-of-time (AOT) compilation.
tl;dr; nope, you can't do this and this has nothing to do with the ng-bootstrap project, but rather with design decisions behind Angular.

By looking at the docs you need to use the property [innerHTML], but to be clear only use it when you trust the code!!
So should be something like this:
<td [innerHTML]="record"></td>

Related

Angular html custom element from typescript [duplicate]

I'm setting HTML returned from the API in my Angular component:
<div [innerHTML]="content"></div>
content in this example is something like this:
<table>
<tr>
<td>[audioPlayer:file.mp3]</td>
</tr>
</table>
Now I would like to inject the actual component inside the table cell.
If I make a certain container, I can create the component with createComponent:
audioPlayerComponentRef: ComponentRef<AudioPlayerComponent>;
#ViewChild('placeholder', { read: ViewContainerRef }) container;
const factory: ComponentFactory<AudioPlayerComponent> =
this.componentFactoryResolver.resolveComponentFactory(AudioPlayerComponent);
this.audioPlayerComponentRef = this.container.createComponent(factory);
Then I can inject it into a container in the template:
<div #placeholder></div>
However, going back to my original goal, I can't use such a container, as the component needs to be injected into a specific position into an innerHtml block.
I've been brainstorming all day, but I can't see any way to achieve this.
Generally speaking, this is contrary to the way Angular works. [innerHTML] is not parsed for any Angular functionality. No component selectors or even a ViewContainerRef can be found there. Rather, even remotely suspicious HTML, CSS and JS is removed as a security measure as Angular only trusts its own templates.
So InnerHTML is a no-go. But I was in the same boat myself and have written a library to solve this exact problem. With it, you can freely load dynamic components into strings without compromising security. If you're still stuck on this, you might wanna have a look at it.

Pug/Jade: Typeahead.js breaks css of entire form

I got some problems implementing typeahead.js
Current setup:
I use Bootstrap v.3.3.7
I implemented jQuery 3.2
I downloaded the typeahead.bundle.min.js v.0.11.1 from Github
I added the JS file to my project and linked it on the
I implemented the typeahead stuff as described in their docs here
I added (an empty CSS) class named .typeahead to init the JS stuff
NOTE: All the typeahead stuff (live-search) works great, but typeahead destroys my css.
-
My working Pug/Jade searchbar:
.flipkart-navbar-search.smallsearch.col-xs-12.qSearchBar(style="margin-left:30px;margin-top:15px;")
.row
input.flipkart-navbar-input.col-xs-11(type='text' id="searchInput" placeholder='Übungen suchen...' autofocus)
button.flipkart-navbar-button.col-xs-1
svg(width='15px' height='15px' fill="white")
path(d='.....')
Result:
-
The code, when I add the .typeahead class to let it init typeahead (also gave it some random other names, the classname is not relevant):
.flipkart-navbar-search.smallsearch.col-xs-12.qSearchBar(style="margin-left:30px;margin-top:15px;")
.row
input.flipkart-navbar-input.col-xs-11(type='text' id="searchInput" placeholder='Übungen suchen...' autofocus).typeahead
button.flipkart-navbar-button.col-xs-1
svg(width='15px' height='15px' fill="white")
path(d='.....')
Results in:
-
Why is that? I mean of course typeahead brings its own classes like tt-hint e.g. to display the results - but these aren't any problem. Why does typeahead actually make my searchbar look like this.
This happens because like most JS/jQuery plugins, typeahead.js also modifies the DOM structure of the elements that it works on.
So, the updated DOM after initialisation of typeahead would not be the same as what you wrote in your html or jade. Your existing CSS rules may or may not apply to this new DOM structure as intended now.
Solution
You need to update your CSS rules, so they target the updated DOM after initialisation of typeahead.js.
To view the updated DOM, you can use inspect element feature of browsers or developer tools etc to view the DOM structure in real time.

What should be a React Component and what should be just an HTML?

I'm prototyping the new homepage for my personal website. I made the following pen: Homepage on React #1.
I want the website to use React, not necessarily because it will benefit from it but primarily because I want to learn React.
If you take a look at the pen, you can see a lot of components looking just like this:
/**
* The main title.
*/
const Title = () => <h1 className="Title">Chuckeles</h1>;
or this:
/**
* The row component. Places items, you guessed it, in a row.
*/
class Row extends React.Component {
render() {
return <div className="Row">{ this.props.children }</div>;
};
};
These components don't do anything special. They just hide the underlying HTML. My question is this. Should I have components like these? Or should I just use the HTML tag, for instance in case of the Title component, use
<h1 className="Title">Chuckeles</h1>
directly?
It might seem that these "small" components are a waste of space, but they are not.
Imagine tomorrow one of the designers wants to change the class of your Titles. If it is just one component, it can be changed there, and there won't be any "hunt" to find all the usage for it. While if you had inlined it everywhere this would be a nightmare.
The basic idea is to make your "lowest level" components contain HTML, they do the "dirty" work (DOM, style), Your higher components should do composition and logic.
I try not to mix HTML type tag and other components in one component. This makes it so that I have a lot of small HTML components, but they are very easy to maintain, and I get a nice separation of business components, and presentation components.
You can go that approach but I prefer the props to spread it like:
return <div {..this.props}>{ this.props.children }</div>;
and then the div you can reuse also in other places.
What you have mentioned here are typically referred to as either Dumb components or stateless functions. They are perfectly fine and should be always preferred over static html so long as there's a re-use/enhancement possibility.

Dynamically re-bind html.ValidationMessageFor html helper?

Some background information, I am using ASP.NET with the MVC framework and html helpers.
I currently have a dynamic table where each row has a series of input boxes. Each of these input boxes has a validation message. This works completely fine for the first row. However, when other rows are dynamically added (with the IDs' being changed along with other attributes to match the row number) the validation message no longer works.
Both the row and validation message span are being replicated properly.
In JQuery, this is usually just a problem with the binding, so for each row I would simply re-bind the IDs'. However I am not really to sure how to approach them in ASP.NET.
Any assistance would be appreciated.
Thanks
Alright, I have finally figured this out.
In MVC, in order to handle the validation, it import a JQuery file known as jquery.validate.unobtrusive.js.
However, similar to JQuery, this only occurs at the very beginning when the page is loaded. So, when you add a new dynamic element, you need to remove the bindings and the re-bind them again.
Basically, in your function for adding a new element, put the following lines of code AFTER you have added the new element:
$("#form").removeData("validator");
$("#form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("#form");
For example:
function addInfoDynamic()
{
document.getElementById("#myDiv").innerHTML += "New Content";
$("#form").removeData("validator");
$("#form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("#form");
}

storing additional data on a html page

I want to store some additional data on an html page and on demand by the client use this data to show different things using JS. how should i store this data? in Invisible divs, or something else?
is there some standard way?
I'd argue that if you're using JS to display it, you should store it in some sort of JS data structure (depending on what you want to do). If you just want to swap one element for another though, invisible [insert type of element here] can work well too.
I don't think there is a standard way; I would store them in JavaScript source code.
One of:
Hidden input fields (if you want to submit it back to the server); or
Hidden elements on the page (hidden by CSS).
Each has applications.
If you use (1) to, say, identify something about the form submission you should never rely on it on the server (like anything that comes from the client). (2) is most useful for things like "rich" tool tips, dialog boxes and other content that isn't normally visible on the page. Usually the content is either made visible or cloned as appropriate, possibly being modified in the process.
If I need to put some information in the html that will be used by the javascript then I use
<input id="someuniqueid" type="hidden" value="..." />
Invisible divs is generally the way to go. If you know what needs to be shown first, you can improve user experience by only loading that initially, then using an AJAX call to load the remaining elements on the page.
You need to store any sort of data to be structured as HTML in an HTML structure. I would say to properly build out the data or content you intend to display as proper HTML showing on the page. Ensure that everything is complete, semantic, and accessible. Then ensure that the CSS presents the data properly. When you are finished add an inline style of "display:none;" to the top container you wish to have dynamically appear. That inline style can be read by text readers so they will not read it until the display style proper upon the element changes.
Then use JavaScript to change the style of the container when you are ready:
var blockit = function () {
var container = document.getElementById("containerid");
container.style.display = "block";
};
For small amounts of additional data you can use HTML5 "data-*" attribute
<div id="mydiv" data-rowindex="45">
then access theese fields with jQuery data methods
$("#mydiv").data("rowindex")
or select item by attribute value
$('div[data-rowindex="45"]')
attach additional data to element
$( "body" ).data( "bar", { myType: "test", count: 40 } );