Compile template string in innerHTML - html

I am new to angular. I am trying render some dynamic template strings that are coming from a server in a component.
The component looks like this -
<div [innerHTML]='templateString'></div>
In component.ts file, we have
obj = {
prop: 'text to display'
}
templateString = '<p class="text-primary">{{obj.prop}}</p>' // this is dynamic, e.g. received from an http request
If we leave it like this, it will render as '{{obj.prop}}' whereas I want it to show is 'text to display'. Currently I have written a script that takes the templateString and obj and returns the properties by using .split('{{') etc. Is there some simpler built-in way to do this in angular? I.e. compiling the template strings dynamically onChanges or onInit, so that I can take advantage of ngFor to display values inside an array property for instance.
arr = [
{prop: 'text1'},
{prop: 'text2'}
]
templateString = '<p *ngFor="let item of arr">{{item.prop}}</p>'
Currently I am using a custom syntax [[arr::{{this.prop}}]] which my script can read and iterate over arrays, but it is pretty unreliable and non standard.
I have seen this Angular: bind variables inside [innerHtml], but it seems overqualified since I do not need to put other components inside the template string. Just standard html, with some directives like ngFor, ngIf etc,

I think you can just use inline concatenation
`this is the string ${this.foo} more string here`

No rocket science needed. This will work for you!
templateString = '<p class="text-primary">'+ this.obj.prop + '</p>' ;

Related

Why I Can't Write Objects in <li> Tag

When I writing my JSON data to HTML tag it's writing but don't write object. It's write [object Object]:
○Data1 ○wash dishes ○[object Object]
○find some break ○[object Object]
I'm trying to do lists with pointing JSON database but it's looks like that. I'm calling my JSON with that code:
var db_note = objpick(data);
db_note.date.forEach(function(element) {
tabledatednote.insertAdjacentHTML( 'beforeend',"<li>" + element + " </li>");
/* I just writed to this part because is just changing "no_date.>date<" part while displaying other JSONs */
});
objpick.js is an external file
function objpick(data){
for(i in data){ var result = data[i] }
return result
};
and there is my JSON database
{
"nodate": ["wash dishes", "find some bread"],
"date": [{"01/01/2077" : "Cyberpunk Meet"}, {"25/05/2005" : "Buney?"}],
"bookmark" : ["Data1"]
}
Ultimately what's being displayed is a string. So the code converts whatever you want to display to a string. For simple values, this conversion is easy. It's consistent and obvious what the resulting string is for a single value.
But objects are not simple values. They are potentially complex. And unless otherwise defined on your object(s), the default string representation for an object is: [object Object]
Some of the things you are display are values:
"find some bread"
But some of them are objects:
{"25/05/2005" : "Buney?"}
For the objects, you'd need to tell the code how to display it. Some options I can think of are:
Manually. For example, check if a certain property exists on the object and, if it does, display that property's value.
JSON-encode the object and display the resulting JSON string.
Override .toString() on your object(s).
Which you choose is up to you, and for the same reason that you're seeing the current default behavior... Because only you know how you want/expect that object to be displayed.

How can I set HTML string in DOM and bind to an object?

I have markup like this in my angular html component template:
<div *ngIf="htmlTemplate && jsonObj" [innerHTML]="htmlTemplate"></div>
I have my jsonObj variable coming from an endpoint as:
{ firstname: 'Dave' }
and my htmlTemplate string variable coming from an endpoint as:
<strong>Hi....{{firstname}}</strong>
So far, I have managed to get the htmlTemplate rendering in the page, using the [innerHTML] binding, but it's not doing the bind + replacement with the model value from the JSON object.
Q) Is there a way I can make Angular take this html + json obj and render it?
The string output by htmlTemplate will not be interpolated by Angular once it is part of the page. So if the sting is <strong>Hi....{{firstname}}</strong> that is exactly what you will see on the page, including the {{ firstname }} part.
You will need to set the variable in the code file when the result comes from the endpoint:
this.htmlTemplate = `Hello...${result.data.firstname}`
Change this as appropriate for the structure of your returning data.
So the string is, for example, Hello... Dave.

Can you use 'require' in react to import a library?

In my react project, I'm trying to convert XML data from an API call into JSON (using a library called xml-js).
As per the documentation, I'm importing the library in my parent component as follows
const convert = require('xml-js')
and then attempting the convert the API data as follows
const beerList =
'<Product>
<Name>Island Life IPA</Name>
<Volume>300ml/473ml</Volume>
<Price>$10/$13</Price>
<ABV>6.3%</ABV>
<Handpump>No</Handpump>
<Brewery>Eddyline</Brewery>
<IBU/>
<ABV>6.3%</ABV>
<Image>islandlife.png</Image>
<Country>New Zealand</Country>
<Description>Fruited IPA</Description>
<Pouring>Next</Pouring>
<IBU/>
<TapBadge/>
<Comments/>
</Product>'
const beerJs = convert(beerList,{compact: true, spaces: 4})
The errors are telling me that 'convert' is not a function, which tells me that the library isn't being imported. So is the issue with using 'require' syntax, and if so, what alternative would work in react?
which tells me that the library isn't imported
No. If that were the case, you wouldn't even get that far, your require call would throw an error.
Instead, it tells you that convert is not a function - which it isn't! Look at it in a debugger or log it, and you'll see it's an object with several functions inside. You can't call an object like a function.
Take a look at the xml-js docs again:
This library provides 4 functions: js2xml(), json2xml(), xml2js(), and xml2json(). Here are the usages for each one (see more details in the following sections):
var convert = require('xml-js');
result = convert.js2xml(js, options); // to convert javascript object to xml text
result = convert.json2xml(json, options); // to convert json text to xml text
result = convert.xml2js(xml, options); // to convert xml text to javascript object
result = convert.xml2json(xml, options); // to convert xml text to json text
So the solution is to call convert.xml2json and not convert:
const beerJs = convert.xml2json(beerList, {compact: true, spaces: 4})
Or maybe you want an actual object and not a JSON string, then you'd use convert.xml2js (in which case the spaces option is useless):
const beerJs = convert.xml2js(beerList, {compact: true})

parse model data to JSON object

I need to convert a list of model objects into a JSON list.
<a data-model="#Model.Schools"></a>");
The list of schools is parsed to a jquery eventhandler when the above button is pressed (I left some code out here)
Here, I naturally want to read the list of schools to a json list.
var items = JSON.stringify(button.data('model'))
var items2 = JSON.parse('"' + button.data('model') + '"')
I tried the above, however without any luck, it still yells at me for trying to convert a System.Collections.Generic.List`1.
Also I tried to serialize the object to JSON at the button, i.e. #HTML.raw(Json.Serialize(Model.Schools) but it just gives me an empty object in my jQuery...
Therefore, how do I convert a Model object to a json object in jQuery?
If I get your problem statement correctly, it seems you are pretty much there.
you need to serialise your list into Razor attribute (don't use #Html.Raw helper as it will not escape your string and mess with your page):
Full .net framework
<a id="btnModel" data-model="#Json.Encode(Model.Schools)" onclick="process()">TEST</a>
<!-- assuming you have Newtonsoft.Json package installed, the following line should also work-->
<a id="btnModel" data-model="#Newtonsoft.Json.JsonConvert.SerializeObject(Model.Schools)" onclick="process()">TEST</a>
and then in your Javascript:
function process() {
var m = $('#btnModel').data('model');
alert(JSON.stringify(m));
}
check out this dotnet fiddle for working example
.net core 3
Apparently the built-in serilizer somehow garbles the formatting so it needs proper html encoding. This unfortunately will mean you have to decode it in Javascript. One way to avoid this hassle would be to output your json string into javasctipt block (see second example)
<a id="btnModel" data-model="#Html.Encode(Json.Serialize(Model.Schools))" onclick="process()">Method 1 - Lotsa pain</a>
<a id="btnModel1" onclick="process1()">Method 2 - Less back and forth</a>
function decodeHtml(html) {
var txt = document.createElement("textarea");
txt.innerHTML = html;
return txt.value;
}
function process() {
var a = $('#btnModel').data('model');
a = JSON.parse(decodeHtml(a));
alert(JSON.stringify(a));
}
function process1() {
var a = #Json.Serialize(Model.Schools);
alert(JSON.stringify(a));
}

Manually parse json data according to kendo model

Any built-in ready-to-use solution in Kendo UI to parse JSON data according to schema.model?
Maybe something like kendo.parseData(json, model), which will return array of objects?
I was searching for something like that and couldn't find anything built-in. However, using Model.set apparently uses each field's parse logic, so I ended up writing this function which works pretty good:
function parse(model, json) {
// I initialize the model with the json data as a quick fix since
// setting the id field doesn't seem to work.
var parsed = new model(json);
var fields = Object.keys(model.fields);
for (var i=0; i<fields.length; i++) {
parsed.set(fields[i], json[fields[i]]);
}
return parsed;
}
Where model is the kendo.data.Model definition (or simply datasource.schema.model), and json is the raw object. Using or modifying it to accept and return arrays shouldn't be too hard, but for my use case I only needed a single object to be parsed at a time.
I actually saw your post the day you posted it but did not have the answer. I just needed to solve this problem myself as part of a refactoring. My solution is for DataSources, not for models directly.
kendo.data.DataSource.prototype.parse = function (data) {
return this.reader.data(data);
// Note that the original data will be modified. If that is not what you want, change to the following commented line
// return this.reader.data($.extend({}, data));
}
// ...
someGrid.dataSource.parse(myData);
If you want to do it directly with a model, you will need to look at the DataReader class in kendo.data.js and use a similar logic. Unfortunately, the DataReader takes a schema instead of a model and the part dealing with the model is not extracted in it's own method.