Angular ng-repeat with input - javascript

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);
}
});

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>

Define and get values from angularJS table

Here is my angularjs code to get values in a table and save. If I put some data in table and save, Its working fine but if I click save without entering any data in table it shows error as
TypeError: $scope.item is undefined
Here is my code and please help me. I am a newbie in angularJS
<div ng-app="Myapp">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-route.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-messages.js"></script>
<script>
var Myapp = angular.module('Myapp', ["ngRoute"]);
</script>
<div ng-controller="orderFormController">
<table id="item_table">
<thead>
<tr class="headings">
<th class="column-title">Item </th>
<th class="column-title">Rate</th>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="text" name="item" ng-model='item[0]'>
</td>
<td>
<input type="text" name="rate" ng-model='rate[0]'>
</td>
</tr>
<tr>
<td>
<input type="text" name="item" ng-model='item[1]'>
</td>
<td>
<input type="text" name="rate" ng-model='rate[1]'>
</td>
</tr>
</tbody>
</table>
<button type="button" ng-click='saveorder()' >SAVE ORDER</button>
</div>
<script>
Myapp.controller('orderFormController', ['$scope', '$http', function ($scope, $http) {
var data = {};
data['item'] = [];
$scope.saveorder = function () {
var rowCount = 3;
for (i = 1; i < rowCount; i++) {
data['item'][i] = {'item': $scope.item[i], 'rate': $scope.rate[i]}
}
alert(data);
}
}]);
</script>
$scope.item is not defined anywhere except for in that for loop, if there are no values in the table, then $scope.item will remain undefined. You could simply declare it prior to the for loop, and set some init values, which could be done in the controller, or by using the ng-init directive.
Also, I would recommend using the ng-repeat directive for your table rows, it will create a template per item from a collection, which makes your code easier to manage. Here's the documentation: ngRepeat
modify your html to only include this not 2 rows of input
<td>
<input type="text" name="item" ng-model='item'>
</td>
<td>
<input type="text" name="rate" ng-model='rate'>
</td>
and modify your saveOrder
$scope.saveorder = function () {
if (!($scope.item.length && $scope.rate.length)){
alert('can\'t be empty');
return;
}
data['item'].push({'item': $scope.item, 'rate': $scope.rate});
$scope.item = "";
$scope.rate = "";
console.log(data['item'][data['item'].length - 1]);
alert(data);
}

AngularJS: modify value within ng-repeat

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.

the 'this' keyword don't work for $http 'success' method in Controller of Angular

I want to load a list of colleges from an ajax call and display in UI.
I am using AngularJS framework for this example.
the bellow code if for College.html
<div class="page-header" ng-controller="CollegeController as collegeCntrl">
<div class="page-header">
<h3>Add/Manage Colleges</h3>
</div>
<ng-view />
</div>
The below code is for list.html,
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>College-ID</th>
<th>College-Name</th>
<th>Edit College</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="college in collegeCntrl.collegeList | orderBy : 'collegeName'">
<td>{{college.collegeId}}</td>
<td>{{college.collegeName}}</td>
<td>
Edit
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4">
Add College
</td>
</tr>
</tfoot>
</table>
The below code is from college.js,
angular.module("CollegeModule",[])
.constant("collegeListURL","../rest/ser/college/list/One")
.controller("CollegeController",function($location, $http, collegeListURL){
$location.url("/loadingImage");
$http.get(collegeListURL).success(function(data){
this.collegeList = data;
$location.url("/college/list");
});
this.editCollege = function(college){
this.selectedCollege = college;
}
}
in the above code please look at the code for
$http.get(collegeListURL).success(function(data){
this.collegeList = data;
$location.url("/college/list");
});
the 'this' keyword don't work for the success method,
so i replaced the above code with the below block of code
(function(collegeCntrl){
$http.get(collegeListURL).success(function(data){
collegeCntrl.collegeList = data;
$location.url("/college/list");
});
})(this);
And it worked.
So my question is the code which worked for me can be a good practice in AngularJS controller,
or there is a other way to refer 'this' ?
There's a question on the matter of this vs $scope.
The common use for $scope is anything that you want to access directly on your HTML.
You can use this for methods or attributes you'd like to keep away from the $scope. But I'd rather stay consistent and not mix this and $scope so I usually stick to $scope.
You should inject $scope in your controller and set $scope.collegeList = data;
Then in you html instead of college in collegeCntrl.collegeList, you just remove collegeCntrl.: college in collegeList

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

Categories

Resources