Displaying JSON array results one per line in a table cell - javascript

I have a table which displays the column "air segments". The air segments come as a JSON array from the server(see picture), I need to display the contents of the air segments column one per line in a table cell. Right now its getting displayed as a complete string with a comma(See picture below).
.
So the HTML code is as follows:
<!-- ko foreach: $parents[0].outputsToDisplay($data) -->
<td>
<span data-bind="foreach: $data, visible: $parents[2].outputs()[$parent.index()].internalname ==='air_segments', text: splitAirSegments($data)"><br></span>
</td>
<!-- /ko -->
The outer 'for each' supplies the $data to the td, which are the results to be populated in the table.
The visible binding property makes sure that only column air_segments gets populated.
The outputs() is an observable array in the js file.
I need to code a JS method "splitAirSegments" such that it returns the air segments one by one and with help of 'br' I break the line which would eventually make the air segments appear one per line in a single table cell.
What I tried:
self.splitAirSegments = function (arr) {
return arr;
}
The way I understood it was, the 'for each' from the 'span' would send each of the air segment to this function and the HTML will display it with line breaks as soon as the function returns the value.
What can be the correct approach? Are there any other ways to split the air segments(with delimiter as a comma) which is now displaying all the air segments together with a comma.
Kindly help.

On the lines of user #Origineil's fiddle the below worked for me:
<!-- ko foreach: $parents[0].outputsToDisplay($data) -->
<td>
<span data-bind="if: $parents[1].Outputs()[$index()].InternalName === 'air_segments'">
<span data-bind="foreach: $data">
<span data-bind="text: $data"></span>
<br/>
</span>
</span>
</td>
<!-- /ko -->

Related

Treating output from a database as HTML code within angular

I'm creating a front end application which looks at a database of Hearthstone cards allowing you to sort and search them. However, the Text displayed on the cards (Within the database) has HTML formatting within it such as <b> </b>
EG:
The card "Toxic Arrow" has a text field containing:
Deal $2 damage to a minion. If it survives, give it <b>Poisonous</b>.
currently the rendering function looks as follows:
`<tr *ngFor = "let card of cards">
<td> {{card.text}} </td>
<td> <img [src] = 'card.img'
[title] = 'card.name'
[style.width.px] = ImageWidth> </td>
</tr> `
and currently the output within the table shows this:
Deal $2 damage to a minion. If it survives, give it <b>Poisonous</b>.
I'm looking for a way to format this text quickly inside this loop to remove the $ and use the already existing HTML <b> tag
I'm not using the older AngularJs, I'm using the most current up to date version of Angular.
You can replace the first <td> in your code with <td [innerHTML]="card.text"> </td>.
This will cause the text to be displayed with HTML formatting as per the tags present in the input string.

Nested ng-repeat with dynamic input

I am trying to display a JSON response in a table using ng-repeat. The problem is that not all objects recieved are the same. All of them have a date, short message and long message. There are also ones with an additional value list, differing in length. This list should be diplayed underneath the long message within its own table or list. I use the alert.slice().reverse() because I want the newest entries to be on top. The new objects are inserted using .push({values}).
<tbody class="AlTbody" ng-repeat="alerts in alerts.slice().reverse()" ng-class="className">
<tr class="Altr Aldate">
<td ng-show="{{alerts.Date}}"><b>{{alerts.Date}}:</b>
</td>
</tr>
<tr class="Altr Alshort " ng-click="toggleDetail($index)">
<td>{{alerts.S}}</td>
</tr>
<tr class="Altr " ng-show="activePosition == $index">
<td class="msgL">{{alerts.L}}
<!-- 1) <p ng-show="{{item.List}}"><br><ul><li>Previous values:</li> <li ng-repeat="vals in ValueList">{{vals.value}}</li></ul> </p>-->
<!-- 2) <p ng-show="{{List.txt}}"> <br><ul><li>Previous values:</li> <li ng-repeat="List in alerts.List">{{List.txt}}</li></ul> </p>-->
</td>
</tr>
</tbody>
I already tried two approaches as seen in the code. The first one displayed the list correct however it was displayed underneath every long message instead of only the one it belongs to. I used a new variable.
var l=valList.length;
scope.List=true;
while(l>-1){
scope.ValueList.push({value: valList[l]});
l--;
}
The second approach did not work at all because I could not find an index.
var l=valList.length;
var indexV= jQuery.inArray(currdate,scope.alerts.Date);
while(l>-1){
scope.alerts[indexV].List.push({txt: valList[l]});
l--;
}
edit:
This is the current output. There you can see two objects( date, short message and long message) and both of them have the previous values section. However only the upper object is supposed to diplay the list of previous values.
What you are trying to achieve is entirely possible, my advice is to start at a known point and work from there.
I have put together a jsfiddle to show you how nested ng-repeats will work. try and work from that point. As a side note it looks like your JSON structure is overly complex, if you can simplify that down I would.
https://jsfiddle.net/roscorcoran/wyu7tgxm/
<div ng-app="App" ng-controller="Ctrl1">
<div ng-repeat="alert in alerts">
<a ng-if="alert.Date">{{alert.Date}}</a>
<p ng-repeat="val in alert.L.vals">
<a ng-if="val && val.value">{{val.value}}</a>
</p>
<p ng-repeat="item in alert.List">
<a ng-if="item && item.txt">{{item.txt}}</a>
</p>
</div>
</div>
You can try to add a ng-if statement inside the ng-repeat loop:
<p ng-if="{{values.list}}"><br><ul><li>Previous values:</li> <li ng-repeat="vals in values.list">{{vals.value}}</li></ul> </p>-->
Okay so this works for me now. It still always displays "Previous Values:" but the values only display when they actually belong to the message.
<ul ng-if="alerts.List.vals"><li>Previous values:</li> <li ng-repeat="val in alerts.List.vals" >{{val.value}}</li></ul>
This might not be the best and most elegant solution but it works.
if(valList){
scope.alerts.push({Date:currdate,S:msgSn,L:msgLn, List:{ vals:[{value:valList[0]},{value:valList[2]},{value:valList[4]},{value:valList[6]}] } });
}else{
scope.alerts.push({Date:currdate,S:msgSn,L:msgLn });
}
I only display the even indexes of the value array because the list of values was a string which I split and every uneven entry is "):" which I don't need to display.

Is it possible to highlight multiple rows of a single column in a multi-column HTML table?

For purposes that are very central to my apps purpose, I display text content in an HTML table in a UIWebView. Here is an example of what that HTML looks like:
<table width = "100%">
<tbody>
<tr>//Row 1
<td>
<div id = "guid">
Here is the text of the first row, first cell in the table
</div>
</td>
<td>
<div id = "guid">
Here is the text of the first row, second cell in the row
</div>
</td>
</tr>
<tr>//Row 2
<td>
<div id = "guid">
Here is the text of the second row, first cell in the row
</div>
</td>
<td>
<div id = "guid">
Here is the text of the second row, second cell in the row
</div>
</td>
</tr>
</tbody>
</table>
Again, it might not seem like I need to use a table, but it is essential to other functionality of the app - more s can be added to the same row.
I am trying to add a highlight tool to my app, and am running into some issues due to the fact that I am working with a table. Here is an example of the type of selection I am trying to make (same structure, different content):
Once the selection is made, it is quite easy to set a highlight to the text using execCommand. Quite easy if there is only one column of data that is. Take a look at what happens when I try and highlight the selection I made above:
It highlights the cell from the other column! The reason I am using a table is that I need to make sure that each block of text in the row (within the tr/td tags) starts at the same time, even though they could have varying heights, and one could be longer than the other and make the row taller as a result. This approach ensures unity at the row level.
Anybody have any ideas what I could do to fix this?

Knockout.js Tracking Selected Checkboxes

I have a html grid that returns a checkbox with each row. Currently I have these bound with knockout to my viewmodel. I've gotten far enough to capture the id of what is checked for a row but I'm not sure how to make Knockout give me a list of all rows checked and the content of every cell for the row.
Ultimately the intent is to let users select multiple rows from this table and then export that data. So I need a good way to gather the entire row up.
I've only been using Knockout for about a week so am I trying to get it to track something that perhaps I'd be better of just looping through the table with javascript?
<tbody data-bind="foreach: projectListing">
<tr data-bind="css: $data.rowclass">
<td><input type="checkbox" data-bind="value: $data.id, checked: $root.selectedRows, click: $root.toggleRowSelection"/></td>
<td data-bind="text: $data.SORT_ID"></td>
<td data-bind="text: $data.PROJ_ID"></td>
</tr>
</tbody>
*I know that code isn't enough to go on but I had to put something in here so I could list a link to jsFiddle.
I have a fiddle going that represents this to show code I have so far. What I'd like to do with this fiddle is each time I check the checkbox, the entire row content should show up. That would get me to the place I need to be in my real project.
Any ideas on how to go about this?
Here is what I have so far.
http://jsfiddle.net/robhortn/ad2Yu/4/
Instead of getting the id with the checked binding, you can create a selectedItems computed to get the selected items objects
self.selectedItems = ko.computed(function() {
return self.availableItems().filter(function(item) {
return item.Selected();
});
});
Html
Selected Books:
<div data-bind="foreach: $root.selectedItems">
<span data-bind="text: Name"></span>
<br/>
</div>
See this JSFiddle

Achieve fixed column number of a table with data-binding

I have a table with bound data (KnockoutJS) like this:
...
<tr>
<th class="rotated">Row 1</th>
<!-- ko foreach: Dog-->
<td>
<p data-bind="text: Name">
</p>
</td>
<!-- /ko -->
</tr>
...
Problem is that I'd like to have fixed number of columns, for example 5, but sometimes there isn't much data so there are less than 5 columns generated. I'd like to know what is the best way how to add the columns so they are always 5.
I made a Javascript function which goes through all the rows, counts the <td> tags and add <td> tags if needed. Is there other option?
You should always use an array with 5 items even though it has empty values in it.
For example:
var Dog = [{Name:"dog1"},{Name:"dog2"},{Name:""},{Name:"dog3"},{Name:""}];

Categories