AngularJS: modify value within ng-repeat - javascript

I have a simple table in Angular:
<table>
<tr ng-repeat="row in $data">
<td>{{row.name}}</td>
<td>{{row.surname}}</td>
</tr>
</table>
that would render something like this:
<table>
<tr>
<td>Johnathan</td>
<td>Smith</td>
</tr>
<tr>
<td>Jane</td>
<td>Doe</td>
</tr>
</table>
but I have a dynamic search function that reloads the table and I need to highlight the search string in results like so (the search word is "John"):
<table>
<tr>
<td><span class="red">John</span>athan</td>
<td>Smith</td>
</tr>
</table>
now I hoped that something like this would work:
<table>
<tr ng-repeat="row in $data">
<td>{{myFunction(row.name)}}</td>
<td>{{row.surname}}</td>
</tr>
</table>
but it doesn't. Any way to make this work?
UPDATE: Solved, solution proposed by #loan works in this case.

As you'll see in the example below, you can do something similar to this.
Example
In your existing loop you can add the custom filter as follows:
<body ng-controller="TestController">
<h1>Hello Plunker!</h1>
<input type="text" ng-model="query" />
<ul>
<li ng-repeat="item in data | filter:query">
<!-- use the custom filter to highlight your queried data -->
<span ng-bind-html="item.name | highlight:query"></span>
</li>
</ul>
</body>
In your JavaScript file you can create the custom filter:
(function() {
'use strict';
angular.module("app", []);
//to produce trusted html you should inject the $sce service
angular.module("app").filter('highlight', ['$sce', function($sce) {
function escapeRegexp(queryToEscape) {
return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
}
return function(matchItem, query) {
return $sce.trustAsHtml(query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem);
};
}]);
angular.module("app")
.controller('TestController', ['$scope',
function($scope) {
$scope.query = ""; //your scope variable that holds the query
//the dummy data source
$scope.data = [{
name: "foo"
},{
name: "bar"
},
{
name: "foo bar"
}];
}
]);
})();
if you want you can replace the html in the filter with your values:
<strong>$&</strong>
to
<span class="red">$&</span>

use ng-class, so the html for your td becomes
<td ng-class = "{red: row.name == searchStr}">{{row.name}}</td>
There are other formats for ng-class and my html may be dodgy I use haml mostly but check the docs on ng-class

You can use angular-ui's highlight module. You can simply use it like this:
DEMO
HTML
<div>
<input type="text" ng-model="searchText" placeholder="Enter search text" />
</div>
<input type="checkbox" ng-model="caseSensitive" /> Case Sensitive?
<table>
<tbody>
<tr ng-repeat="row in $data">
<td ng-bind-html="row.name | highlight:searchText:caseSensitive"></td>
<td>{{row.surname}}</td>
</tr>
</tbody>
</table>
You can download it via bower, instructions are provided in their github page.
Note: Add angular's ngSanitize to avoid an $sce unsafe error.

Related

passing $scope objects to ng-if and ng-class ternary condition not working

**main.js:**
$scope.status = [
{name:'SQL', stat:"up"},
{name:'Web Server', stat:"down"},
{name:'Index', stat:"down"}
];
**index.html:**
<table>
<tr>
<td ng-repeat="x in status">
<div ng-if="{{x.name}}=='SQL'"> {{x.stat}} </div>
</td>
</tr>
</table>
<table>
<tr>
<td ng-repeat="x in status">
<div ng-if="{{x.name}}=='SQL'" ng-class="{{x.stat}}=='up'? 'squareGreen':'squareRed'"> {{x.name +" : "+x.stat}} </div>
</td>
</tr>
</table>
I am trying to pass status array to index.html to compare the 'name' to a string then apply class squaregreen or red depending upon comparison of 'stat' to 'up' or 'down'. The goal is to match the name of the server and apply green when up and red when down. I have 2 problems below. 1. parse error in syntax for ng-if 2. all servers are applied Squarered, though 1st server(sql)'s 'stat' is 'up'
Remove all the curly braces from your ng-if and ng-class expressions and it should work. E.G:
main.js:
$scope.status = [
{name:'SQL', stat:"up"},
{name:'Web Server', stat:"down"},
{name:'Index', stat:"down"}
];
**index.html:**
<table>
<tr>
<td ng-repeat="x in status">
<div ng-if="x.name=='SQL'"> {{x.stat}} </div>
</td>
</tr>
</table>
<table>
<tr>
<td ng-repeat="x in status">
<div ng-if="x.name=='SQL'" ng-class="x.stat=='up'? 'squareGreen':'squareRed'"> {{x.name +" : "+x.stat}} </div>
</td>
</tr>
</table>
Curly braces are not necessary here because ng-if and ng-class bindings are evaluated as scope expressions already. Use curly braces when a directive does not do this by default (e.g. with '#' bindings). AngularJS docs on scope binding
Take out your curly braces. ng-if="x.name === 'SQL'"
You don't need to use the extrapolation {{}} operator within ng-if and you need to use the {} within your ng-class
<div ng-if="x.name == 'SQL'" ng-class="{x.stat=='up'? 'squareGreen':'squareRed'}"> {{x.name +" : "+x.stat}} </div>

Angularjs add element to DOM when clicking

I want to create a table which contains dynamic Content. When clicking on an element, the Details should Show up in the next line. So i creatied the following:
<table ng-controller="TestCtrl">
<tr ng-repeat-start="word in ['A', 'B', 'C']">
<td><!-- Some Information, Image etc --></td>
<td ng-click="showDetails(word)">{{word}}</td>
</tr>
<!-- This is only visible if necessary -->
<tr ng-repeat-end ng-show="currentDetail == word">
<td colspan="2" ng-attr-id="{{'Details' + word}}"></td>
</tr>
</table>
And I have the following js code:
angular.module('maApp', []).controller("TestCtrl", function($scope, $document, $compile){
$scope.showDetails = function(word){
var target = $document.find("Details" + word);
//I checked it - target is NOT null here
//target.html("<div>Test</div>");
//target.append("<div>Test</div>");
var el = $compile("<div>Test</div>")($scope);
target.append(el);
//Show tr
$scope.currentDetail = word;
};
});
I also tried the commented Solutions above but nothing of it works (The tr is showing up however). I guess there is something wrong with $document.find("Details" + word) but I don't know what.
Ultimately I want to add an <iframe> and the source would contain the word.
Does anybody see what I'm doing wrong here?
No need for weird non-angulary DOM manipulation: All you need is this.
HTML:
<table ng-controller="TestCtrl">
<tr ng-repeat-start="word in ['A', 'B', 'C']">
<td><!-- Some Information, Image etc --></td>
<td ng-click="showDetails(word)">{{word}}</td>
</tr>
<tr ng-show="currentDetail==word" ng-repeat-end>
<td colspan="2">Details {{word}}</td>
</tr>
</table>
JS:
angular.module('myApp', []).controller("TestCtrl", function($scope, $document, $compile){
$scope.showDetails = function(word) {
$scope.currentDetail = word;
};
});
http://jsfiddle.net/HB7LU/20074/
$document.find in jqlite is limited to tag name only. You have to add jquery for anything more.
See what is suported in the docs.
you have all you need built into angular already, you don't need the Javascript at all.
see this plunker example
<table style="width:100%;">
<thead style="background-color: lightgray;">
<tr>
<td style="width: 30px;"></td>
<td>
Name
</td>
<td>Gender</td>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="person in people">
<td>
<button ng-if="person.expanded" ng-click="person.expanded = false">-</button>
<button ng-if="!person.expanded" ng-click="person.expanded = true">+</button>
</td>
<td>{{person.name}}</td>
<td>{{person.gender}}</td>
</tr>
<tr ng-if="person.expanded" ng-repeat-end="">
<td colspan="3">{{person.details}}</td>
</tr>
</tbody>
</table>

Cannot get Angular Filter to display Html Entity

I am trying to display a Green Check Mark for "True" values and a Red Cross for "False values in my MVC View using angular. Using a filter, I can display the unicode check (u+2713) and cross (u+2718), but they want a "green" check and a "red" cross. I included angular-sanitize.js on my page and tried to use the ng-bind-html-unsafe directive, when I do the field is blank.
Can anyone tell me what I am missing here?
Here is my HTML page:
<script src="~/Scripts/app/AccordionCtrl.js"></script>
<script src="~/Scripts/app/checklist-model.js"></script>
<script src="~/Scripts/angular-sanitize.js"></script>
<div ng-app="myModule" ng-controller="AccordionCtrl">
<table class="table">
<thead style="background-color:#0e438d; color:white">
<tr>
<td>Company Name</td>
<td>City</td>
<td>State</td>
<td>System ID</td>
<td>Releast Status</td>
<td>Training Tracker</td>
<td>SSQ Complete</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="contractor in contractors">
<td>{{contractor.vchCompanyName}}</td>
<td>{{contractor.vchOprCity}}</td>
<td>{{contractor.vchOprStateID}}</td>
<td>{{contractor.CompanyID}}</td>
<td>{{contractor.ReleaseStatus}}</td>
#*<td>{{contractor.TrainingTracker|applyMarks}}</td>*#
<td><span ng-bind-html-unsafe="contractor.TrainingTracker | applyMarks"></span></td>
<td>{{contractor.SSQComplete|applyMarks}}</td>
</tr>
<tr>
<td>&#10004</td>
</tr>
</tbody>
</table>
</div>
</div>
Here is my filter code in my controller:
app.filter("applyMarks", function(){
return function(input){
if(input == true){
//return '\u2713';
return '&#10004';
}
else
{
return '\u2718'
}
};
ng-bind-html-unsafe has been deprecated since angular 1.2 version.
You need to use $sce to sanitize your html.
Markup
ng-bind-html="contractor.TrainingTracker | applyMarks | trustedhtml"
Code
app.filter('trustedhtml', function($sce) {
return $sce.trustAsHtml;
});

Angular JS object as ng-model attribute name

I'm creating a dynamic angular js application wherein I want to use a textbox as a searchtext for the filter of a table. Here's a preview on what I am doing:
As of now, my code looks like this
<table>
<thead>
<tr class="filterrow">
<td data-ng-repeat="col in items.Properties">
<input id="{{col.DatabaseColumnName}}" type="text"
data-ng-model="search_{{col.DatabaseColumnName}}"/>
<!-- Above Here I want to dynamically assign the ng-model based on Databasecolumnname property-->
</td>
</tr>
<tr>
<th data-ng-repeat="col in items.Properties">{{col.ColumnTitle}}</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="content in items2.Contents | filter: search_{{col.DatabaseColumnName}}: search_{{col.DatabaseColumnName}}">
<td data-ng-repeat="col in items.Properties">
{{content[col.Databasecolumnname ]}}
</td>
</tr>
</tbody>
</table>
I already tried the approach of using $compile but I wasn't able to implement it. Any ideas in an approach? Thanks!
EDIT: Plnkr - plnkr.co/edit/5LaRYE?p=preview
You can do this by setting a base object for your ng-Models. So in your controller you will have:-
$scope.search = {};
and in your view do:-
<input ng-attr-id="{{col.DatabaseColumnName}}" type="text"
data-ng-model="search[col.DatabaseColumnName]"/>
With this your dynamic ng-model will be assigned to the search base object, ex:- if col.DatabaseColumnName is col1 then ngModel would be $scope.search.col1

Angular ng-repeat with input

I have a view like this:
<table class="table">
<tr data-ng-repeat="exercise in exercises x">
<td>
<input type="number" data-ng-model="?????????" />
</td>
<td>
{{exercise.Name}}
</td>
</tr>
</table>
I'm wondering what should I put as data-ng-model so I can use two-way data binding i.e., the input's value, in my controller?
I've tried data-ng-model="{{exercise.Name}}" but that resulted in errors.
Also, how can I reference certain input in the controller? Can I do something like this: $scope.InputOne = ...
Use data-ng-model="exercise.Name" without the {{}} brackets.
I suggest you start at the angular tutorial.
for two-way-bind use ng-model, and one-way-bind use ng-bind or {{}} brackets.
this example demonstrates to use the two ways and how to get information of the object.
ps: the controller should not "see" the view directly.
<body data-ng-app="app">
<div data-ng-controller="TestCtrl">
<table>
<tbody>
<tr data-ng-repeat="exercise in exercises">
<td>
<input type="number" data-ng-model="exercise.Name" />
</td>
<td data-ng-bind="exercise.Name"></td>
<td><button data-ng-click="getInformation($index)">Get information</button></td>
</tr>
</tbody>
</table>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.min.js"></script>
var app = angular.module('app', []);
app.controller('TestCtrl', function($scope) {
$scope.exercises = [{Name:1},
{Name:2},
{Name:3},
{Name:4}
];
$scope.getInformation = function(index) {
alert($scope.exercises[index].Name);
}
});

Categories

Resources