I'm trying to add CSS styles to a string computed in Javascript. It goes through a series of transformation functions:
var fieldSetTransformation = setFieldTransformation(iteration);
fieldSetTransformation = stylePropertyName(fieldSetTransformation);
This value then is passed to a table generated in a directive through AngularJS's ng-repeat:
<tbody class="tableBody">
<tr ng-repeat="line in linesArray">
<td ng-repeat="column in ::columns" width="{{::column.width}}" ng-class="{
'center-text' : (!line[column.key] || line[column.key].length === 0)
}">{{line[column.key] !== undefined ? line[column.key] : '--'}}<span ng-if="column.key == 'user'">
<i id="plus-icon-styling"
class="fa fa-plus-circle action-icon">
</i>
</span>
</td>
</tr>
</tbody>
So I'm struggling to append it to an existing container.
What I have tried so far?
Injecting the HTML directly into the returned value:
var htmledField = [
'<span class="propertyNameHighlight">' + fieldSetTransformation,
'<span>'].join("\n");
];
No use, since this does not seem to be accepted anymore by current navigators (correct me if wrong) since it's a security issue.
The thrown result is just <span class="propertyNameHighlight">000000</span>
appearing in the table.
Creating the element, then appending it in the view
Also a no-go:
function stylePropertyName(data){
var newSpan = document.createElement('span');
newSpan.setAttribute('class', 'propertyNameHighlight');
document.getElementsByClassName("tableBody").appendChild(newSpan);
newSpan.innerHTML = data;
return data;
}
This returns a null function exception.
I have also checked this question, which seemed the closest to my query, but in my case there is no clear container neither to wrap up the resulting string.
TL;DR: What I'm trying to achieve?
This green text over here:
That represents a cell. The data is not directly passed, it's generated dynamically through a series of functions and ng-repeats.
Any help or related disregarded question that I could get is greatly appreciated. Thanks!
As suggested by commenter Stanislav Kvitash (thanks!), I solved this by using ngBindHtml :
<tbody class="tableBody">
<tr ng-repeat="line in linesArray">
<td ng-repeat="column in ::columns" width="{{::column.width}}" ng-class="{'center-text' : (!line[column.key] || line[column.key].length === 0)}">
<span ng-bind-html="line[column.key] !== undefined ? line[column.key] : '--'"></span>
<span ng-if="column.key == 'user'">
<i id="plus-icon-styling"
class="fa fa-plus-circle action-icon">
</i>
</span>
</td>
</tr>
</tbody>
Related
I face issue Cannot hide or remove URL exist as plain text on column name offilneUrl
I already do as link so that no need to plain text URL above
So I need to hide or remove or empty URL plain text above word page link .
<tbody>
<ng-container *ngFor="let repcon of ReportControl">
<tr *ngFor="let rep of contentBody">
<td *ngFor="let coln of headerCols">
<span>
{{rep[coln]}}
</span>
<div *ngIf="coln==repcon.fieldName">
<div *ngIf="repcon.columnType==1">
<a (click)="goToLink(rep.offilneURL)">page link</a>
</div>
</div>
</td>
</tr>
</ng-container>
</tbody>
I try as below
{{rep.offilneURL || " "}} but it repeated offlineURL with every row
so what i do to solve issue
see image below the text with green color that i need to remove because it .
post updated
structure of content body on ts file
this._displayreport.GetReportDetailsPaging(this.searchData).subscribe((data: any[]) => {
this.reportdetailslist = data;
this.headerCols = Object.keys(data[0]);
this.contentBody = data;
});
data structure for content body :
companyName: "Innovasic, Inc."
done: "0"
notImpacted: "0"
notificationDate: "2009-11-12"
offilneURL: "https://source.z2data.com/2019/1/13/8/55/47/351/662203977/21527_SPCN.PDF"
onlineURL: "N/A"
pending: "3"
reportDate: "2020-05-07"
revisionID: "272299243"
teamName: "MFG"
totalCount: 79
already have link
Updated post
https://stackblitz.com/edit/create-4ud1rg?file=app%2Fapp.component.html
according to my structure I need to change
<span *ngIf="coln != 'onlineURL'">
{{rep[coln]}}
</span>
to
<span *ngIf="coln != 'repcon.filedName'">
{{rep[coln]}}
</span>
It's just because:
<span>
{{rep[coln]}}
</span>
is still displaying the value regardless so just hide it if the column is the url
<span *ngIf="repcon.columnType != 1">
{{rep[coln]}}
</span>
Base on the content body structure and logic you shared, you can hide the link as follows.
Based on logic ==>
<span *ngIf="repcon.columnType!=1">
{{rep[coln]}}
</span>
I think you are showing the link based on the condition repcon.columnType==1, So check for converse to hide the offline link.
This can be handled in other way as well.
Based on structure ==>
<span *ngIf="coln != 'onlineURL'">
{{rep[coln]}}
</span>
Hope this helps.
I have a html page that contains a table with date, staffID and shift. Shift has a value of 0 (morning) or 1 (afternoon). It is generated as follows:
function staffSchedule ($scope, $http) {
$http
.get('/api/schedule/2017/02')
.then(function(response) {
var data = response.data;
$scope.shifts = data;
console.log(data);
})
.catch(function(errorResponse) {
console.log('Error: ' + errorResponse.status);
});
}
<table>
<tr>
<th>Date</th>
<th>StaffID</th>
<th>Shift</th>
</tr>
<tbody ng-repeat="shift in shifts">
<tr>
<td>{{shift.staffid}}</td>
<td>{{shift.date}}</td>
<td>{{shift.type}}</td>
</tr>
</tbody>
</table>
The code returns the data as it should do but I want to extend it to do something more.
I want the code to dynamically substitute the 0 for Fontawesome sun <i class="fa fa-sun-o" aria-hidden="true"></i> and 1 for Fontawesome moon <i class="fa fa-moon-o" aria-hidden="true"></i>. Any idea how I can do this with my current setup please?
Here is what I did in my code to get it to work.
<td>
<i class="fa" ng-class="{'fa-hourglass-start':schedule.shift==0,
'fa-hourglass-end':schedule.shift==1}">
</i>
</td>
To explain:
Grab my icons from font awesome http://fontawesome.io/
ng-repeat receives requests from a RESTful call via AngularJS
one of the fields in the record returns '0' or '1' (always; required field)
Use fa-hourglass-start if 0 and fa-hourglas-end if 1.
Use ng-class.
Something like:
<td>
<i class="fa" ng-class="{'fa-sun':shift.type==0,'fa-moon':shift.type==1}"></i>
</td>
Note I did not verify the proper FA class names
is there any way to insert additional row in ng-repeat ? Here is the problem.
<tr data-ng-repeat="user in content |pagination: currentPage*limit| limitTo: limit | filter: searchText ">
<td>{{user.imie}}</td>
<td>{{user.nazwisko}}</td>
<td>{{user.data_urodzenia}}</td>
<td>{{user.imie2}}</td>
<td>{{user.imie}}</td>
<td>{{user.imie}}</td>
<td><i ng-click="showDetails()" class="fa fa-plus-square" aria-hidden="true"></i></td>
</tr>
I have this table with repeating. In last cell there is a button that will trigger function to show more details of user. So what i need is, an additional row inserted under presented row.
<tr ng-repeat...></tr>
<tr ng-show="details">additional data row</tr>
and the controller
$scope.details = false;
$scope.showDetails = function(){
if (!details) {
$scope.details = true;
}
else {
$scope.details = false
}
}
Any way to do this ? Tried few approaches and didn't worked out.
You can either put the ng-repeat on the tbody, which will likely cause some issues with styling.
Or you can use ng-repeat-start/end. As of angular 1.2, you can repeat over elements which is pretty cool - to do this you can;
<tr ng-repeat-start="user in content |pagination: currentPage*limit| limitTo: limit | filter: searchText ">
<td>{{user.imie}}</td>
<td>{{user.nazwisko}}</td>
<td>{{user.data_urodzenia}}</td>
<td>{{user.imie2}}</td>
<td>{{user.imie}}</td>
<td>{{user.imie}}</td>
<td><i ng-click="showDetails()" class="fa fa-plus-square" aria-hidden="true"></i></td>
</tr>
<tr ng-repeat-end ng-show="details">additional data row</tr>
More information here.
Hope it helps!
Use your ng-repeat in tbody tag, then you can use your additional row on a new tr tag
like this below way
<tbody data-ng-repeat="user in content |pagination: currentPage*limit| limitTo: limit | filter: searchText ">
<tr>
<td>{{user.imie}}</td>
<td>{{user.nazwisko}}</td>
<td>{{user.data_urodzenia}}</td>
<td>{{user.imie2}}</td>
<td>{{user.imie}}</td>
<td>{{user.imie}}</td>
<td><i ng-click="showDetails()" class="fa fa-plus-square" aria-hidden="true"></i></td>
</tr>
<tr>
// your additional row
</tr>
</tbody>
And one more thing, Your code is totally wrong
$scope.details = false;
$scope.showDetails = function(){
if (!details) {
$scope.details = true;
}
else {
$scope.details = false
}
}
this above code will open all row, not particular row. So you need maintain with this by Array of $index
my goal is to be able to copy data from a table row to another table row.
if the data from 2015 has not changed from 2016 the user needs a quick way of copying the values into the 2016 input fields. the models are dynamically created for these forms. the data you see in this image is assigned to a section. the input models are name 'price_min + section_id', price_max + section_id' , etc...
the history model does not have the section_id added to the end of the model names. so there needs to be a mapping function that i need help with. I need to map the history values to the current model convention and update the view with the values.
currently i have a click function that brings in the matched section history. here is a screen shot of what that looks like.
in that same function i have the 2016 object array with the current model naming convention.
i need to copy the history values into the inputArray. how i go about doing this, i dont know? I have complete control on how this works. and in the plunker you will see how i did this. if i need to change something else to make this work then that is ok. javascript, jquery, lodash, linq.js is currently being used in project.
working plunker
working plunker
$scope.copyHistoryData = function (section) {
var selected = Enumerable.From(sectionsHistory).Where("x => x.section_id == '" + section.section_id + "'").ToArray();
selected = selected[0];
var inputArry = section.sectionInputs;
};
I'm not sure why you use such complex data structure, but here is my take on it
$scope.copyHistoryData = function (section, input) {
var historyId=input.model.split('-')[0];
var historyVal=section.sectionHistory[section.sectionHistory.length-1][historyId];
$scope.model[input.model]=historyVal;
};
To fill all fields:
$scope.copyHistoryData = function (section) {
angular.forEach(section.sectionHistory[section.sectionHistory.length-1], function (historyVal, historyId) {
var inputModel=historyId+"-"+section.section_id;
$scope.model[inputModel]=historyVal;
});
};
http://plnkr.co/edit/OOEmgzKB1pqKjSJMayVF?p=preview
I agree with #ssh. The data structure is a mess. I think this is a better representation of what it should look like. Probably not the best but you shouldn't have to iterate through the data to then display it like that.
http://plnkr.co/C9DWV1dSvkk8lcYdm0An?p=preview
<div class="hpanel" ng-repeat="section in sections">
<div class="panel-body">
<div class="row">
<div class="col-xs-12">
<ul class="list-inline">
<li>
<h5>
<b>SecID</b>
</h5>
<span>{{section.section_id}}</span>
</li>
<li>
<h5>
<b>Section Name</b>
</h5>
<span>{{section.section_name}}</span>
</li>
</ul>
<hr/>
<button ng-click="section.new_section_history = section.section_history">copy row</button>
<table>
<tr>
<td ng-repeat="label in labelIndex">
{{label.label}}
</td>
</tr>
<tr>
<td ng-repeat="label in labelIndex">
{{section.section_history[label.index]}}
</td>
</tr>
<tr>
<td ng-repeat="label in labelIndex">
<input ng-model="section.new_section_history[label.index]"/>
</td>
</tr>
<tr>
<td ng-repeat="label in labelIndex">
<button ng-click="section.new_section_history[label.index] = section.section_history[label.index]">copy</button>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
I have checked your code, and I agree with #Steven Kaspar, the anchors in every row doesn't make much sense. I have solved it using jQuery (I know it doesn't follow your scheme with Angular, but it's another solution).
I have added a new <tr> to add a button inside it.
Check this out:
<tr>
<td colspan="10"><button class="copyRow">Copy complete row</button></td>
</tr>
And in the app.js:
$(document).on("click", ".copyRow", function(){
var $btn = $(this),
$tbody = $btn.parent().parent().parent(),
$trs = $tbody.find("tr");
$.each($trs.eq(0).find("td"), function(index, td){
$trs.eq(1).find("td").eq(index).find("input").val(parseFloat($(td).text().replace("$", "")));
});
})
Here is the updated plunker. I hope it helps
I have this HTML structure:
<tr class="project-details">REMOVE THIS</tr>
<tr class="project-description">
<td colspan="6">
<div class="project-desc-inner">
<div class="project-synopsis">
<p class="trunk8">This is an entry</p>
</div>
<div class="project-verification">
<span class="verfied-badge"> <~~~~~~~~~~ THIS SPAN
<span class="currency-symbol">$</span>
<span class="icon-tick"></span>
Verified
</span>
</div>
<div class="project-actions">
<a href="#">
<button class="btn">LOL</button>
</a>
</div>
</div>
</td>
</tr>
And I hope that the entire <tr class="project-details">REMOVE THIS</tr> plus its contents will be remove completely
This is what I have so far:
function showAlert()
{
var projectDescriptions = document.querySelectorAll('tr.project-description'),
projectDescriptions = Array.prototype.slice.call(projectDescriptions);
projectDescriptions.forEach(function(el) {
if (el.querySelector('span.verfied-badge')) {
}else {
el.parentNode.removeChild(el);
el.prev('tr').remove();
}
});
}
What it does is select the <tr> with the <span> I am looking for, then delete the entire span. This part el.prev('tr').remove(); is not working, any alternative?
Thanks!
The body of the else clause:
(function removePreviousSibling(sibling) {
if (sibling.nodeName === 'TR' && sibling.classList.contains('project-details')) {
return sibling.parentNode.removeChild(sibling);
}
removePreviousSibling(sibling.previousSibling);
}(el.previousSibling));
el.parentNode.removeChild(el);
The IIFE ensures if there is an extra text node between the two <tr> elements that the text node will be skipped and not deleted if you just did called a removeChild on the previousSibling of the target element.
Take a look over the information at MDN's DOM page. It's got a great set of interface documentation and tutorials.
prev is a method of a jQuery object. HTMLElement object has no prev method. For selecting the previous element sibling you can use the previousElementSibling property.