I have a loop currently in my application located here:
<tr ng-repeat="audit in audctrl.audits | orderBy:'-created_at'">
<td>
{{audit.objects}}
</td>
</tr>
The object's code shows a lot of text, but with a lot of the ↵ symbol.
How would I go about making these replaced?
I have tried
{{audit.object.replace(/\u21B5/g,'<br/>')}}
What would be the best method to make this work?
I would suggest you to write an angular filter. For example:
myApp.filter('multiline', function () {
return function(text) {
return text.replace(/\n/g, '<br>');
}
});
and then call it with pipe:
<tr ng-repeat="audit in audctrl.audits | orderBy:'-created_at'">
<td>
{{audit.objects | multiline}}
</td>
</tr>
#Edit
I'm not sure about your new line character code but you can easy change it. Angular filters are good because they are reusable in other parts of application.
#Edit2
To display html tags in Angular binding u have to use $sce service and ng-bind-html="audit.objects | multiline" instead of {{audit.objects | multiline}}
http://jsfiddle.net/c1qwg776/
Write this in your controller at initialisation:
for(var i=0;i<audctrl.length;i++){
for(var j=0;j<audctrl[i].objects.length;j++){
if(audctrl[i].objects.charCodeAt(j)===10){
var temp=audctrl[i].objects.substring(0,j);
temp+="<br/>";
audctrl[i].objects= temp+audctrl[i].objects.substring(j+5,audctrl[i].objects.length-1);
}
}
}
Related
I have the following custom directive:
angular.module('Interfaces').directive('Interfaces', function() {
return {
restrict : 'A',
scope : {
minor : '#'
},
templateUrl : 'interfaces/interfaces.template.html',
controller : [ '$scope', 'InterfacesService', function InterfaceController($scope, InterfacesService) {
$scope.interfacesService = InterfacesService;
$scope.label = 'Interfaces';
$scope.optional = ($scope.minor == "true");
if ($scope.optional) {
$scope.label = '';
}
$scope.getInterfaces = function getInterfaces() {
return $scope.interfacesService.getInterfaces($scope.minor);
};
} ]
};
});
And the following template
<tr ng-class="{'optional': optional}"><td colspan="5">Just testing</td></tr>
<tr ng-class="{'optional': optional}" ng-repeat="interface in interfaces = (getInterfaces())" >
<td rowspan='{{interfaces.length}}' class='label-column' ng-if="$index === 0">{{label}}</td>
<td colspan='2' class='data'>{{interface.key}}</td>
<td colspan='2' class='data'>{{interface.value}}</td>
</tr>
I am using this directive as part of a table:
<table>
<tbody>
<!-- other table content -->
</tbody>
<tbody interfaces minor="true"></tbody>
<tbody interfaces minor="false"></tbody>
<tbody>
<!-- other table content -->
</tbody>
</table>
The first table row is just added for testing purposes. It correctly has the class "optional" according to the value of the variable 'optional'.
However, those table rows created by ng-repeat never have the "optional" class set, no mattter what the value of the 'optional' variable.
I have found the following article
Angular js Custom Directive on element with ng-repeat - Can't set CSS classes
which suggests using a priority of -1001 in my directive, but neither the 1001 of the original code in that post nor the -1001 suggested in the answer make a difference in my case.
Why is ng-class not applied on the element with the ng-repeat?
Ok, after talking to a friend it seems the problem was the following line in the template:
<tr ng-class="{'optional': optional}" ng-repeat="interface in interfaces = (getInterfaces())" >
Having put the getInterfaces() call in brackets seems to have lead to an endless iteration which stopped the ng-class from being applied. I had seen those error messages but did not make the connection between them and my issue.
I have solved the issue as follows:
Instead of retrieving the data from the InterfacesService, I am now passing them from the outer template as a parameter:
<tbody interfaces minor="true" interfaces="{{information.host.interfaces}}"></tbody>
<tbody interfaces minor="false" interfaces="{{information.host.interfaces}}"></tbody>
And in the directive I've added a new binding:
scope : {
minor : '#',
interfaces: '<'
},
And my interface template now directly references this new binding:
<tr ng-class="{'optional': optional}" ng-repeat="interface in interfaces" >
The reason for attempting to get this information from the InterfacesService instead of passing it into the directive was that I had tried that and failed, using the service had been a workaround.
I stumbled across the same problem again in a slightly different setting (see AngularJs: How to pass part of my data from one component to another) and the answer there (to use a '<' binding instead of '#' allowed me to get rid of the service and hence the
(getInterfaces())
part of my ng-repeat statement.
I already used ngTable with static data before, it worked well (listing, sorting and filtering). I'm using ngTable v 0.8.3
My Goal
This time I want to create a ngTable with data loaded from a Web Service.
I made a custom factory to be able to create my ngTable with future others entities.
Issue
It doesn't work and I have no JS console errors. When I debug, I can clearly see that my method query from my service Employee return me my complete and correct objet containing employees details. I enter in the getData() function, the ngTable is being created, but with empty data.
Relevant and lightweighten code
Here is my HTML markup :
<table ng-table="tableParams" class="table table-striped" show-filter="true">
<tbody>
<tr ng-repeat="employee in $data">
<td data-title="'employee.firstname' | translate" filter="{'firstname' : 'text'}" sortable="'firstname'"><a ui-sref="employee.detail({id:employee.id})">{{employee.firstname}}</a></td>
<td data-title="'employee.lastname' | translate" filter="{lastname : 'text'}" sortable="'lastname'">{{employee.lastname}}</td>
<td data-title="'employee.mail' | translate" filter="{mail : 'text'}" sortable="'mail'">{{employee.mail}}</td>
<td data-title="'employee.phone-number' | translate" filter="{phone_number : 'text'}" sortable="'phone_number'">{{employee.phone_number}}</td>
<td data-title="'employee.birthdate' | translate" filter="{birthdate : 'text'}" sortable="'birthdate'">{{employee.birthdate}}</td>
</tr>
</tbody></table>
my Angular controller :
myapp.controller('EmployeeController', function ($rootScope, $scope, Employee, ngTableParams, ngTableFactory) {
$scope.tableParams = ngTableFactory.create(20, {lastname: 'asc'}); // count, sorting
});
And my Angular factory :
myapp.factory('ngTableFactory', function(ngTableParams, Employee) {
return {
create: function(count, sorting) {
return new ngTableParams({
page: 1, // initial page
count: count, // count per page
sorting: sorting // initial sorting
}, {
total: 0,
getData: function($defer, params) {
Employee.query({page: params.page(), size: params.count()}, function(result) {
$defer.resolve(result);
});
}
});
}
}
});
Edit 1, progresses :
My items are being listed if I remove params from my query method, so it was a bad handling of my Employee service. But, the sort and filter does not work on my table by default. to make sorting works, I have to add this line on my ngTable factory, in the getData() function :
result = $filter('orderBy')(result, params.orderBy());
Normally, the sorting of basic elements works as I added the 'sortable' keyword in my HTML ngtable template columns, and as I'm fetching my data over $data item. Still investigating.
Thanks for your help mates !
As far as I can see, your code works.
Please see https://github.com/masa67/NgTable for a working example (based on Node). I did not change anything (except filled-in the missing parts, maybe the problem is there).
The table formatting is not correct, but at least the data is coming in.
I have an ng-repeat statement where I want to show an image. The image however, should be chosen from where the ng-repeat's ID matches the image object's ID.
I am unsure of how to do this properly, here is psuedo code of what I am trying to do.
<tr ng-repeat="user in rosterData | orderBy:'name'">
<img ng-src="{{champion.imagename WHERE user.id = champion.id}} />
</tr>
Remember that champion.id is an object of champions, so I want to make sure I get the right champion.name to match with the right champion.id when it matches the current ng-repeat user.id
It would be better if you could check those logic inside the controller:
<tr ng-repeat="user in rosterData | orderBy:'name'">
<img ng-src="{{getImage(user.id)}} />
</tr>
In your controller:
$scope.getImage = function(userId) {
var image = "defaultimage";
$scope.champions.forEach(function(champion) {
if(champion.id===userId) {
image = champion.image;
}
});
return image;
}
You will have to put a method in "ng-src" statement, pass the id as a parameter - > iterate array, find match and so on.
Method should be added in controller to $scope property, than just call it :)
I've got an AngularJS webapplication where I use ng-repeat on an array of persons. The json array defines a firstname, lastname and age of the persons.
In my table I'm trying to apply a CSS class to all the young persons using the ng-class directive.
<table class="table table-striped table-hover">
<tr><th>Firstname</th><th>Lastname</th><th>Age</th></tr>
<tr ng-repeat="person in people | filter:search" ng-class="{success: person.isYoung()}">
<td>{{person.firstname}}</td>
<td>{{person.lastname}}</td>
<td>{{person.age}}</td>
</tr>
</table>
Notice I'm trying to call person.isYoung(), which is the method I'm having trouble with. Things work if I use
ng-class="{success: person.age < 30}"
but, I want to move that logic into the Controller instead.
Inside my Controller I've added this;
$scope.isYoung = function (person) {
return person.age < 30;
}
but it seems like that isn't called.
What should my method definition in app.js look like for me to get this working?
ng-class="{success: person.isYoung()}"
The signature of the function is
isYoung(person)
So that's what you need to use in your template:
ng-class="{success: isYoung(person)}"
If you want to be able to use person.isYoung(), then you need to add this function to all the persons in the array :
angular.forEach(persons, function(person) {
person.isYoung = function() {
return person.age < 30;
}
});
I'm designing universal table that reads data and columns from ajax.
In columns description is also filter name which angular should use for a specific column.
But in HTML templates I can't use variables for filter names:/
Is there a solution for that? Or should I code javascript loop with data source?
Here is code example:
<tr ng-repeat="item in data">
<td ng-repeat="col in cols">
{{item[col.source]}}
<span ng-if="col.ngFilter">
{{col.ngFilter}} // ex. "state" filter
{{item[col.source]|col.ngFilter}} //is not working - is looking for "col.ngFilter" not "state" filter.
</span>
</td>
</tr>
You cannot do it in your HTML. First, you need to apply the filter in your controller.
function MyCtrl($scope, $filter) {
$scope.applyFilter = function(model, filter) {
return $filter(filter)(model);
};
}
Then, in your HTML:
Instead of
{{item[col.source]|col.ngFilter}}
use
{{applyFilter(item[col.source], col.ngFilter)}}
For anyone looking to do something like
{{applyFliter(item[col.source], col.ngFilter)}}
where ngFilter might contains some colon separated parameters such as
currency:"USD$":0
I ended up writing this little helper
function applyFilter (model, filter){
if(filter){
var pieces = filter.split(':');
var filterName = pieces[0];
var params = [model];
if(pieces.length>1){
params = params.concat(pieces.slice(1));
}
return $filter(filterName).apply(this,params);
}else{
return model;
}
}