I'm trying to use a wysiwyg in my angular app. What I want to happen is, I query an end point for an array of objects. Then based on the property name the data inside it gets wrapped into a different html tag. Then all the data is concatenated into a string which gets displayed on a wysiwyg in my app.
So JSON that looks like
[
{
"name": "steve",
"age": 33,
"profile": "http://www.profile.com/steve",
"location": "New York"
},{
"name": "john",
"age": 25,
"profile": "http://www.profile.com/john",
"location": "LA"
},
]
Spits out:
"<b>Steve - New York</b>
<br>
<a href='http://www.profile.com/steve'>Url</a>
<br>
<span>33</span>
<br>
<br>
<b>John - LA</b>
<br>
<a href='http://www.profile.com/john'>Url</a>
<br>
<span>25</span>
<br>
<br>"
While this part isn't Angular specific. I think I need to add this code into a service so that it can be reused whenever I would need it an an app.
I'm not sure what this code would look like. Any ideas?
EDIT: For clarification the reason why I'm doing this is because the page has a WYSIWYG on it. A non-technical user needs to be able to edit the data in the WYSIWYG then click a button and the app exports a PDF. The WYSIWYG requires a single string with HTML tags as does the backend of the app which generates the PDF file.
It seems to me that there's really no reason to reinvent the wheel here... why can't you just use a fully supported WYSIWYG editor like TinyMCE? It's got an angular extension through the Angular-UI project here:
https://github.com/angular-ui/ui-tinymce
Then you could write this in your html:
<textarea ui-tinymce="tinyMceOptions" ng-model="parsedResponse"></textarea>
<button ng-click="convertToPdf()">Y U NO DOWNLOAD PDF?</button>
In your controller (or directive):
$scope.tinyMceOptions = {/*Customize here*/};
$scope.parseMyResponse = function(data) {
// do something with data and return as html string
return data;
};
$http.get('/your/resource/url').success(function(result) {
$scope.parsedResponse = $scope.parseMyResponse(result);
});
$scope.convertToPdf = function() {
// do something with $scope.parsedResponse here to get a PDF
};
Edit:
I guess I didn't get what you were asking exactly at first? If you want it in a service all you have to do is something like:
angular.module('app')
.service('Util', function() {
return {
wrapInTag: function(tagName, value) {
return '<' + tagName + '>' + value + '<' + tagName + '/>';
},
parseMyResource: function(response) {
htmlString = '';
angular.each(response, function(item) {
htmlString += this.wrapInTag('h1', item.title);
htmlString += this.wrapInTag('b', item.id);
// Other manipulation...
});
return htmlString;
}
};
});
Then in your controller:
angular.module('app')
.controller('MyCtrl', function(Util){
// Use Util functions here...
});
I've given you some example code for parsing JSON into HTML strings, but I'm afraid I couldn't be more specific as to how to write it. The logic if your parsing function really depends on what you're trying to accomplish as well as what your data model looks like. There's really no straight-forward way to convert JSON to HTML.
Related
I have a problem with JSON data. I want to add a span element inside a string, but it doesn't work. How to ''escape'' string? Below is an example.
{
"text": "Copyright©2020 <span class="test">Gamepix</span> All Rights Reserved."
}
If you're using Typescript you can use in your HTML file [innerHTML].
Example:
<div [innerHTML]="text"></div>
in your typescript file:
text: string = "some text here <span class='yellow'>six pieces</span>, and here";
and in your .scss file:
::ng-deep .yellow {
color: #f5dc27;
}
I know I'm a bit late to this question but I just worked this out for myself! The "render" function takes my data in the JSON key "data" and returns the data in "dataname" as well as my desired html tag (span). Hope this helps!
{
"data": "dataname", render: function (data) {
return data + '<span></span>';
}
},
"Other data keys to follow"
{
},
Here is my Angular data (i write here only one data entry as demo, actually i have so many entry):
var font = angular.module('font', []);
font.controller('fontListCtrl', function($scope) {
$scope.font = [
{
id: "_001",
name: "Kalpurush",
download: "1"
}
]
var download = scope.font.download
});
I want to pass my download ID into inside javascript inside html. but i cannot success.
<div class="fontbox" ng-repeat="font in font">
{{font.name}}
<script>ccount_display('download')</script>
</div>
Please help me, thank you :)
I am making some assumption based on your code/question. If that's not the case, I can modify my solution.
There are couple of issues in your code. I've tried to fix them below:
var font = angular.module('font', []);
font.controller('fontListCtrl', function($scope) {
$scope.fonts = [{
id: "_001",
name: "Kalpurush",
download: "1"
}];
//assuming you're accessing above scope variable, your code had 'scope' but not $scope. And it's an array.
$scope.download = $scope.fonts[0].download;
//assuming you want to use download variable in your HTML.
});
Also the HTML is incorrect. You should do something like below:
ng-repeat="font in fonts"
If i understand the problem correctly you want to pass id into the count_display method you can do that by passing font.id and the use of the <script> tag in this context is not necessary. Hope this helps.
I am trying to pass a new created object to my dot.js partial snippet like this :
try {
var tempFn = doT.template($('#myTpl').text());
var resultText = tempFn({
"foo": "this snippet"
});
$('#result').html(resultText);
} catch (e) {
$('#error').show().html(e);
throw e;
}
#error {
font-weight: bold;
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dot/1.0.3/doT.js"></script>
<!-- Template HERE -->
<script id="myTpl" type="template/doT.js">//<![CDATA[
{{##def.snippet:obj:
<div>How to use {{=obj.x}}</div>
#}}
{{#def.snippet:{"x":it.foo}}}
// ]]></script>
<div id="result"></div>
<div id="error" style="display: none;"></div>
But I get Template has an error: SyntaxError: Unexpected token :
So how can I create and pass object (or multiple params) to a defined partial ?
What's going wrong ?
EDIT:
I have a schedule structure that come from a REST webservice like that :
"schedule": {
"MONDAY": {
"amOpenTime": {
"hours": 8,
"minutes": 30
},
"amCloseTime": null,
"pmOpenTime": null,
"pmCloseTime": {
"hours": 17,
"minutes": 0
}
},
"TUESDAY": {
"amOpenTime": {
"hours": 8,
"minutes": 31
},
"amCloseTime": null,
"pmOpenTime": null,
"pmCloseTime": {
"hours": 17,
"minutes": 40
}
},
....
}
I would to do not repeat my templating for each day because they must be processed in same way (DRY!)
So I consider using partial snippet to print each line of my schedule (morning open/close time and afternoon open/close time).
So as morning and afternoon div sould be threated in same way, I would like to create a second snippet to handle that. But for morning I need to pass only am prefixed data and pm prefixed data for afternoon like that :
{{##def.scheduleHalfDay:fday:
// multiple condition that I ommited
<div class="closed {{fday.type}}">{{fday.openTime.hours}}:{{fday.openTime.minutes}} - {{fday.closeTime.hours}}:{{fday.closeTime.minutes}}</div>
#}}
{{##def.scheduleRow:hday:
{{? (typeof hday.amOpenTime === "undefined" || hday.amOpenTime === null) && (typeof hday.pmCloseTime === "undefined" || hday.pmCloseTime == null) }}
<div class="closed">Closed</div>
{{??}}
{{#def.scheduleHalfDay:{"type": "morning", "openTime": hday.amOpenTime, "closeTime": hday.amCloseTime}}}--{{#def.scheduleHalfDay:{"type": "afternoon", "openTime": hday.pmOpenTime, "closeTime": hday.pmCloseTime}}}
{{?}}
#}}
<div class="agency-schedules">
<div class="line"><div class="agency-schedules-day">Monday</div>{{#def.scheduleRow:it.horaires.MONDAY}}</div>
<div class="line"><div class="agency-schedules-day">Tuesday</div>{{#def.scheduleRow:it.horaires.TUESDAY}}</div>
...
</div>
scheduleHalfDay are not working. So how can I pass my 3 parameters properly (without change data structure) ?
Another way to make it work is to declare your param as a variable.
{{ var param = {"x":it.foo}; }}
{{#def.snippet:param}}
First, your template has HTML in it so you should use .html() to get the template text.
Second, brackets, { and }, are reserved for doT template borders so you can't have them in templates.
Third, you don't need to use a partial there if all you're doing is passing an object to a template:
<script id="myTpl" type="template/doT.js">
{{##def.snippet:
<div>How to use {{=it.foo}}</div>
#}}
{{#def.snippet}}
</script>
Here's the simple working example: https://jsfiddle.net/silkster/wq5tjzrt/
Here's an example of transforming your position data and passing it to doT: https://jsfiddle.net/silkster/wq5tjzrt/2/
EDIT
From the new data you added, it seems what you need is an array of days. What you have in the original JSON data is a regular object with day names as properties. In my 3rd example below, I transform the object into an array of days and pass that to doT to output a schedule and use a partial template to show the opening and closing times for each day.
One edit I had to do in the partial template was to change the snippet so the correct properties are used in the template.
This might be the answer you're looking for:
When you define the partial template, use the variable that will be available when the partial is used. "it" is the default, but if you use the partial in a loop as in my example, then define the partial with the variable as defined within the loop template.
Also, while transforming the data, add any data from calculations that you might need in your template. For example, if you need to determine if the opening time and closing time happen in am or pm, then do that while transforming the data and add the new key/value pairs to the transformed data.
Example 3 using your schedule data: https://jsfiddle.net/silkster/nq6guog9/
I have a column in a Kendo grid that I want to perform some specific logic for when rendering, and am using Angular. I have the grid columns set up using the k-columns directive.
After looking at the documentation, it seemed simple: I could add the template option to my column, define the function to perform my logic, and pass the dataItem value in. What I have looks something like this:
k-columns='[{ field: "Name", title: "Name",
template: function (dataItem){
// Perform logic on value with dataItem.Name
// Return a string
}
}]'
However, running this causes a syntax error complaining about the character '{' that forms the opening of the block in my function.
I have seen several examples of defining a template function in this format. Is there something else that needs to be done for this to work? Am I doing something incorrectly? Is there another way of defining the template as a function and passing the column data to it? (I tried making a function on my $scope, which worked, except I couldn't figure out how to get data passed into the function.)
Thank you for your help.
It appears that defining a column template in this fashion isn't supported when using AngularJS and Kendo. This approach works for projects that do not use Angular (standard MVVM), but fails with its inclusion.
The workaround that a colleague of mine discovered is to build the template using ng-bind to specify a templating function on the $scope, all inside of a span:
template: "<span ng-bind=templateFunction(dataItem.Name)>#: data.Name# </span>"
This is the default column templating approach that is implemented by Telerik in their Kendo-Angular source code. I don't know yet if the data.Name value is required or not, but this works for us.
Warning: Don't have access to Kendo to test the code at the moment, but this should be very close
In your case, you are assigning a a string to the value of k-columns and that string contains the the word function and your curly brace {
You need to make sure the function gets executed ... something like this:
k-columns=[
{
field: "Name",
title: "Name",
template: (function (dataItem){
// Perform logic on value with dataItem.Name
// Return a string
}())
}
];
Note the difference:
We create an object -- a real honest-to-goodness object, and we use an IIFE to populate the template property.
Maybe, it will be useful for someone - this code works for me too:
columns: [
{
field: "processed",
title:"Processed",
width: "100px",
template: '<input type="checkbox" ng-model="dataItem.processed" />'
},
and you get the two-way binding with something like this:
<div class="col-md-2">
<label class="checkbox-inline">
<input type="checkbox" ng-model="vm.selectedInvoice.processed">
processed
</label>
</div>
This can be done via the columns.template parameter by supplying a callback function whose parameter is an object representing the row. If you give the row a field named name, this will be the property of the object you reference:
$("#grid").kendoGrid({
columns: [ {
field: "name",
title: "Name",
template: function(data) {
return data.name + "has my respect."
}
}],
dataSource: [ { name: "Jane Doe" }, { name: "John Doe" } ]
});
More information is available on Kendo's columns.template reference page.
After hours of searching. Here is the conclusion that worked:
access your grid data as {{dataItem.masterNoteId}} and your $scope data as simply the property name or function.
Example
template: '<i class="fa fa-edit"></i>',
I really hope this safes somebody life :)
just use like my example:
}, {
field: "TrackingNumber",
title: "#T("Admin.Orders.Shipments.TrackingNumber")",
//template: '<a class="k-link" href="#Url.Content("~/Admin/Shipment/ShipmentDetails/")#=Id#">#=kendo.htmlEncode(TrackingNumber)#</a>'
}, {
field: "ShippingMethodName",
title: "#T("Admin.Orders.Shipments.ShippingMethodName")",
template:function(dataItem) {
var template;
var ShippingMethodPluginName = dataItem.ShippingMethodPluginName;
var IsReferanceActive = dataItem.IsReferanceActive;
var ShippingMethodName = dataItem.ShippingMethodName;
var CargoReferanceNo = dataItem.CargoReferanceNo;
var ShipmentStatusId = dataItem.ShipmentStatusId;
if (ShipmentStatusId == 7) {
return "<div align='center'><label class='label-control'><b style='color:red'>Sipariş İptal Edildi<b></label></div>";
} else {
if (ShippingMethodPluginName == "Shipping.ArasCargo" || ShippingMethodPluginName == "Shipping.ArasCargoMP") {
template =
"<div align='center'><img src = '/content/images/aras-kargo-logo.png' width = '80' height = '40'/> <label class='label-control'><b>Delopi Aras Kargo Kodu<b></label>";
if (IsReferanceActive) {
template =
template +
"<label class='label-control'><b style='color:red; font-size:20px'>"+CargoReferanceNo+"<b></label></div>";
}
return template;
}
I want to bind a JSON object to a HTML element.
e.g.
I have a object "person" with the attributes "firstName", "lastName"
<div class="person-list">
<div class="person-list-item">
<div>John</div> ---> bind it to person.firstName
<div>Smith</div> ---> bind it to person.lastName
</div>
</div>
so, if a value of the HTML elements gets changed, then will also the object person gets updated.
is this possible in any way?
i use:
jquery
ASP.NET MVC 3
If you'll be doing this a lot in your application, you may want to bring in a library such as the excellent Knockout.js which uses MVVM to do bindings as you describe.
Your markup would look something like this:
<div data-bind="text: firstName"></div>
<div data-bind="text: lastName"></div>
And in your JavaScript:
function MyViewModel() {
this.firstName = "John";
this.lastName = "Smith";
}
ko.applyBindings(new MyViewModel());
You can also use a data set if there are many "people." Try out this tutorial if you would like to learn how to do that: Working with Lists and Collections.
Other useful links:
Introduction tutorial
Excellent demo video (about 30 minutes)
First, add id attributes to your markup (you could do this with the DOM but for clarity's sake ids are probably best suited for this example):
<div class="person-list-item">
<div id="firstname">John</div>
<div id="lastname">Smith</div>
</div>
Use a jQuery event handler to update the fields whenever they are modified (this is an inefficient solution but gets the job done- worry about optimizing once you have something functional):
// declare your object
function person(firstn, lastn) {
this.firstname = firstn;
this.lastname = lastn;
}
var myGuy = new person("John", "Smith");
$(document).ready(function () {
$("#firstname").change(function () {
myGuy.firstname = $("#firstname").val();
});
$("#lastname").change(function () {
myGuy.lastname = $("#lastname").val();
});
// etc...
});
Now every time the fields are updated your object will be too.
You can parse the JSON to turn it into a JavaScript object:
var data = $.parseJSON(json_string);
// or without jQuery:
var data = JSON.parse(json_string);
If I understood your question correctly, you should have JSON that look like this:
[
{
"firstName": "John",
"lastName": "Smith"
},
{
"firstName": "Another",
"lastName": "Person"
} // etc
]
So you can just loop through the people like so:
$(document).ready(function() {
var str = '[{"firstName":"John","lastName":"Smith"},{"firstName":"Another","lastName": "Person"}]',
data = $.parseJSON(str);
$.each(data, function() {
var html = '<div class="person-list-item"><div>' + this.firstName + '</div><div>' + this.lastName + '</div></div>';
$('#person-list').append(html);
});
});
Fiddle: http://jsfiddle.net/RgdhX/2/
Simple one-way approach using jquery...
var resp = your_json_data;
$(function () {
$(".jsondata").each(function () {
$(this).html(eval($(this).attr("data")));
});
});
then in the page...
<span class="jsondata" data="resp.result.formatted_phone_number" />
I recommend taking a look at Knockout. Setting up data binding like you are looking for is very straightforward with it.
You can use one of the MVC/MVVM libereries such is Backbone.js or Knockoutjs.