Filtering on a formatted datefield - angularjs

I've started recently with AngularJS, and I've come across this problem.
I'm filtering a list with a Angular Filter object. It all works, but I want to be able to type a date value to filter the date column. Problem is, the date that comes from my webservice is (ofcourse) in another format than the showed date.
Here is an example:
View:
Name: <input type="text" ng-model="search.Name"><br>
Date: <input type="text" ng-model="search.Date"><br>
<table>
<tr ng-repeat="item in filtered = (list | filter:search)">
<td>{{item.Name}}</td>
<td>{{item.Date | date:'dd-MM-yyyy'}}</td>
</tr>
</table>
Controller:
app.controller('MainCtrl', function($scope) {
$scope.list = [{
Name: "Item1",
Date: "2018-08-06T13:43:11.82Z"
},{
Name: "Item2",
Date: "2018-08-05T13:43:11.82Z"
},{
Name: "Item3",
Date: "2018-08-04T13:43:11.82Z"
},{
Name: "Item4",
Date: "2018-08-03T13:43:11.82Z"
}
];
$scope.search = {};
$scope.$watch('search', function (newVal, oldVal) {
$scope.filtered = filterFilter($scope.list, newVal);
}, true);
});
working example:
http://plnkr.co/edit/O7j1DAzoxArHK4mnjyeP?p=info
How can I alter this, so I can type the date-value as formatted?

At this case you should create custom filter:
angular.module('plunker', []).controller('MainCtrl', function($scope) {
$scope.list = [{
Name: "Item1",
Quantity: 21,
Date: "2018-08-06T13:43:11.82Z"
}, {
Name: "Item2",
Quantity: 20,
Date: "2018-08-05T13:43:11.82Z"
}, {
Name: "Item3",
Quantity: 31,
Date: "2018-08-04T13:43:11.82Z"
}, {
Name: "Item4",
Quantity: 25,
Date: "2018-08-03T13:43:11.82Z"
}];
$scope.search = {};
}).filter('custom', function() {
return function(array, search) {
function Norm(x) {
return (x + '').toLocaleLowerCase();
}
return array.filter(function(x) {
for (var prop in search) {
if (prop != 'Date' && search[prop] &&
Norm(x[prop]).indexOf(Norm(search[prop])) == -1)
return false;
}
if (x.Date) {
var formatted = x.Date.substring(0, 10).split('-').reverse().join('-');
if (search.Date && !formatted.startsWith(search.Date))
return false;
return true;
}
});
}
});
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js">
</script>
<body ng-app='plunker' ng-controller="MainCtrl">
Name: <input type="text" ng-model="search.Name">
<br> Quantity: <input type="text" ng-model="search.Quantity">
<br> Date: <input type="text" ng-model="search.Date">
<br>
<table>
<tr ng-repeat="item in list | custom : search | orderBy : 'Quantity'">
<td>{{item.Name}}</td>
<td>{{item.Quantity}}</td>
<td>{{item.Date | date:'dd-MM-yyyy'}}</td>
</tr>
</table>
</body>

Html:
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS</title>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.2.x" src="https://code.angularjs.org/1.2.28/angular.js" data-semver="1.2.28"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
Name:
<input type="text" ng-model="search.Name">
<br>
Date:
<input type="text" ng-model="search.Date">
<table>
<tr ng-repeat="item in list2 | filter : search.Date">
<td>{{item.Name}}</td>
<td>{{item.Date}}</td>
</tr>
</table>
</body>
</html>
Js:
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope, $filter) {
const list = [{
Name: "Item1",
Date: "2018-08-06T13:43:11.82Z"
},{
Name: "Item2",
Date: "2018-08-05T13:43:11.82Z"
},{
Name: "Item3",
Date: "2018-08-04T13:43:11.82Z"
},{
Name: "Item4",
Date: "2018-08-03T13:43:11.82Z"
}
];
$scope.list2 = list.map(x => (
{
Name: x.Name,
Date: $filter('date')(x.Date, 'dd-MM-yyyy')
})
);
});

Related

Angular js - How to do strict and progressive search on same field?

I'm trying to do strict and progressive search on same fields in 2 different ways. That is when filter through drop down it should to a strict search and through input search it should do a progressive search. I tried to do it using <tr ng-repeat="x in names | filter:{name:name||dropdownFieldName:true, country:country}"> but is giving some error, Its not working.
Please check the bellow code and help me to solve this issue
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="namesCtrl">
<select id="fieldDropdownHtml" ng-model="fieldSelected" ng-options="x.name for x in names" ng-change="searchOnField()">
<option value=""></option>
</select>
<table border="1" width="100%">
<tr>
<th ng-click="orderByMe('name')">Name</th>
<th ng-click="orderByMe('country')">Country</th>
</tr>
<tr>
<td><p><input type="text" ng-model="name" ng-disabled="disablese"></p>
<td><p><input type="text" ng-model="country"></p>
</td>
</tr>
<tr ng-repeat="x in names | filter:{name:name||dropdownFieldName, country:country}">
<!--tr ng-repeat="x in names | filter:{name:name||dropdownFieldName:true, country:country}" -->
<td>{{x.name}}</td>
<td>{{x.country}}</td>
</tr>
</table>
</div>
<script>
angular.module('myApp', []).controller('namesCtrl', function($scope) {
$scope.disablese = false;
$scope.names = [
{name:'Jani',country:'Norway'},
{name:'Carl',country:'Sweden'},
{name:'Margareth',country:'England'},
{name:'Hege',country:'Norway'},
{name:'Joe',country:'Denmark'},
{name:'Gustav',country:'Sweden'},
{name:'Birgit',country:'Denmark'},
{name:'Jani1',country:'England'},
{name:'Jani',country:'Norway'}
];
$scope.searchOnField = function() {
var e = document.getElementById("fieldDropdownHtml");
var strUser = e.options[e.selectedIndex].text;
angular.forEach($scope.names, function(dsElement) {
if (dsElement.name === strUser) {
$scope.dropdownFieldName = dsElement.name;
console.log($scope.dropdownFieldName);
}
if(document.getElementById('fieldDropdownHtml').selectedIndex == 0){
$scope.dropdownFieldName= undefined;
}
if(document.getElementById('fieldDropdownHtml').selectedIndex != 0){
$scope.disablese = true;
$scope.name = "";
}
else{
$scope.disablese = false;
}
});
}
});
</script>
</body>
</html>
Additional to Allabakash answer, you can use this code to your controller to make it simpler and minimize vanilla JavaScript codes:
angular
.module('myApp', [])
.controller('namesCtrl', function ($scope) {
$scope.disablese = false;
$scope.names = [
{ name: 'Jani', country: 'Norway' },
{ name: 'Carl', country: 'Sweden' },
{ name: 'Margareth', country: 'England' },
{ name: 'Hege', country: 'Norway' },
{ name: 'Joe', country: 'Denmark' },
{ name: 'Gustav', country: 'Sweden' },
{ name: 'Birgit', country: 'Denmark' },
{ name: 'Jani1', country: 'England' },
{ name: 'Jani', country: 'Norway' }
];
$scope.searchOnField = function () {
if ($scope.fieldSelected) {
$scope.dropdownFieldName = $scope.fieldSelected.name;
$scope.name = null;
$scope.disablese = true;
} else {
$scope.dropdownFieldName = undefined;
$scope.disablese = false;
}
};
});
You can achieve this by separating filters like below.
ng-repeat="x in names | filter:{name:name||dropdownFieldName}: disablese | filter: { country:country }"
Hope this helps.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="namesCtrl">
<select id="fieldDropdownHtml" ng-model="fieldSelected" ng-options="x.name for x in names" ng-change="searchOnField()">
<option value=""></option>
</select>
<table border="1" width="100%">
<tr>
<th ng-click="orderByMe('name')">Name</th>
<th ng-click="orderByMe('country')">Country</th>
</tr>
<tr>
<td><p><input type="text" ng-model="name" ng-disabled="disablese"></p>
<td><p><input type="text" ng-model="country"></p>
</td>
</tr>
<tr ng-repeat="x in names | filter:{name:name||dropdownFieldName}: disablese | filter: { country:country }">
<!--tr ng-repeat="x in names | filter:{name:name||dropdownFieldName:true, country:country}" -->
<td>{{x.name}}</td>
<td>{{x.country}}</td>
</tr>
</table>
</div>
<script>
angular.module('myApp', []).controller('namesCtrl', function($scope) {
$scope.disablese = false;
$scope.names = [
{name:'Jani',country:'Norway'},
{name:'Carl',country:'Sweden'},
{name:'Margareth',country:'England'},
{name:'Hege',country:'Norway'},
{name:'Joe',country:'Denmark'},
{name:'Gustav',country:'Sweden'},
{name:'Birgit',country:'Denmark'},
{name:'Jani1',country:'England'},
{name:'Jani',country:'Norway'},
{name:'Jani',country:'Harway'}
];
$scope.searchOnField = function() {
var e = document.getElementById("fieldDropdownHtml");
var strUser = e.options[e.selectedIndex].text;
angular.forEach($scope.names, function(dsElement) {
if (dsElement.name === strUser) {
$scope.dropdownFieldName = dsElement.name;
console.log($scope.dropdownFieldName);
}
if(document.getElementById('fieldDropdownHtml').selectedIndex == 0){
$scope.dropdownFieldName= undefined;
}
if(document.getElementById('fieldDropdownHtml').selectedIndex != 0){
$scope.disablese = true;
$scope.name = "";
}
else{
$scope.disablese = false;
}
});
}
});
</script>
</body>
</html>

make JSON array from dynamic form data angular

i have a dynamic form in angular. and i want to send the response as json. how do i generate JSON from the form?
here's the complete code,I have to get json, and post it to some api.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="dyf" ng-submit="submit()">
<form name="userFormOne" novalidate>
<table>
<tr class="form-group" ng-repeat="x in names">
<td><label>{{ x.Field }}</label>
</td><td><input type="text" class="form-control" placeholder="{{x.Comment}}" required>
</td>
</tr>
</table>{{data}}
</form>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('dyf', function($scope, $http) {
$http.get("http://localhost:5000/gu")
.then(function (response) {$scope.names = response.data;console.log(response.data);});
$scope.data ={};
});
</script>
</body>
</html>
In AngularJs we use ng-model to bind inputs value to our controller, sample:
This full sample to figure out how to create a simple form, from array and how to send it as JSON to your API.
Note: On submit check your console, and see the objects value.
var app = angular.module("app", []);
app.controller("ctrl",
function ($scope) {
var options = [
{ name: "a" },
{ name: "b" },
{ name: "c" }
];
$scope.names = [
{ id: 1, field: "insert name", name: "name", placeholder: "your name is", value:null, type:"text" },
{ id: 2, field: "insert phone", name: "phone", placeholder: "your phone is", value: null, type: "tel" },
{ id: 3, field: "insert age", name: "age", placeholder: "your age is", value: null, type: "number", min: 0, max: 20 },
{ id: 4, field: "select country", name: "country", placeholder: "your country is", value: null, type: "select", options: options }
];
$scope.sendMe = function() {
console.log($scope.names);
}
});
<!DOCTYPE html>
<html ng-app="app" ng-controller="ctrl">
<head>
<title></title>
<meta charset="utf-8" />
</head>
<body>
<form name="userFormOne" novalidate>
<table>
<tr class="form-group" ng-repeat="x in names">
<td>
<label>{{ x.field }}</label>
</td>
<td ng-if="x.type != 'select'">
<input type="{{x.type}}" min="{{x.min}}" max="{{x.max}}" ng-model="x.value" name="{{x.name}}" placeholder="{{x.placeholder}}" ng-required="true">
{{x.value}}
</td>
<td ng-if="x.type == 'select'">
<select ng-model="x.value" name="{{x.name}}" ng-options="item as item.name for item in x.options">
</select>
{{x.value}}
</td>
</tr>
</table>
<button ng-disabled="userFormOne.$invalid" ng-click="sendMe()">sendMe</button>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</body>
</html>

use angular.js to get data from a web endpoint

I need to use angular in order to get data from a web endpoint to fill this table. I have a list created with random names, but I need it to filled with data from a link instead. I still need to create the social media links as well.
Either way, can someone show me how to do it keeping in mind that I don't know much about angular at all. thank you.
html:
<!DOCTYPE html>
<html>
<head>
<title>Angular JS </title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script type="text/javascript" src="folder/main.js"></script>
<script src="http://code.angularjs.org/1.4.8/angular.js"></script>
<script src="http://code.angularjs.org/1.4.8/angular-resource.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>
<link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body ng-app="MyForm">
<div ng-controller="myCtrl">
<h3>List students</h3>
<div class="container-fluid">
<pre>Click header link to sort, input into filter text to filter</pre>
<hr />
<table class="table table-striped">
<thead>
<tr>
<th>Edit</th>
<th>
ID
</th>
<th> Name </th>
<th>Social Media </th>
</tr>
</thead>
<tbody>
<tr>
<td>Filter =>></td>
<td> <input type="text" ng-model="search.name" /></td>
<td> <input type="text" ng-model="search.age" /> </td>
<td><input type="text" ng-model="search.gender" /> </td>
</tr>
<tr ng-repeat="user in students | orderBy:predicate:reverse | filter:paginate| filter:search" ng-class-odd="'odd'">
<td>
<button class="btn">
Edit
</button>
</td>
<td>{{ user.name}}</td>
<td>{{ user.age}}</td>
<td>{{ user.gender}}</td>
</tr>
</tbody>
</table>
<pagination total-items="totalItems" ng-model="currentPage"
max-size="5" boundary-links="true"
items-per-page="numPerPage" class="pagination-sm">
</pagination>
</div>
</div>
</body>
</html>
js:
<script>
var app = angular.module('MyForm', ['ui.bootstrap', 'ngResource']);
app.controller('myCtrl', function ($scope) {
$scope.predicate = 'name';
$scope.reverse = true;
$scope.currentPage = 1;
$scope.order = function (predicate) {
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
$scope.predicate = predicate;
};
$scope.students = [
{ name: 'Kevin', age: 25, gender: 'boy' },
{ name: 'John', age: 30, gender: 'girl' },
{ name: 'Laura', age: 28, gender: 'girl' },
{ name: 'Joy', age: 15, gender: 'girl' },
{ name: 'Mary', age: 28, gender: 'girl' },
{ name: 'Peter', age: 95, gender: 'boy' },
{ name: 'Bob', age: 50, gender: 'boy' },
{ name: 'Erika', age: 27, gender: 'girl' },
{ name: 'Patrick', age: 40, gender: 'boy' },
{ name: 'Tery', age: 60, gender: 'girl' }
];
$scope.totalItems = $scope.students.length;
$scope.numPerPage = 5;
$scope.paginate = function (value) {
var begin, end, index;
begin = ($scope.currentPage - 1) * $scope.numPerPage;
end = begin + $scope.numPerPage;
index = $scope.students.indexOf(value);
return (begin <= index && index < end);
};
});
</script>
the data looks like this:
{"id":"11","name":"A Cooperativa","full_address":"Rua Bar\u00e3o de Viamonte 5, 2400-262 Leiria","location":"Leiria","council":"Leiria","country":"Portugal","lat":"39.7523042","lng":"-8.7825576","type":"various","facebook":"https:\/\/www.facebook.com\/pages\/A-Cooperativa-MerceariaTasca\/1559630810945570","facebook_id":"","gmaps":"https:\/\/www.google.pt\/maps\/place\/R.+Bar%C3%A3o+de+Viamonte+5,+2410+Leiria\/#39.7523042,-8.7825576,17z\/data=!3m1!4b1!4m2!3m1!1s0xd2273a29462db11:0x49a3f9a45cd9eb80","tripadvisor":"http:\/\/www.tripadvisor.com\/Restaurant_Review-g230085-d8154189-Reviews-A_Cooperativa-Leiria_Leiria_District_Central_Portugal.html","zomato":"","website":"","email":"cooperativa.tasca#hotmail.com","telephone":"912635324","active":"1","updated":"2015-08-17 09:01:05"}
I'm not sure if I did get this right, but:
You want to get the students from a web endpoint as json?
Then you would write something like this in angular:
app.controller('myCtrl', function ($scope, $http) {
...
$scope.students = [];
$scope.totalItems = 0;
$http.get('https://www.domain.com/api/resource')
.then(function success(response) {
$scope.students = response.data;
$scope.totalItems = $scope.students.length;
}, function failed(reason) {console.log(reason);})
...
});
But you should use separated files, services etc.

Radio buttons exclusive vertical and horizontally

Hi I'm trying to do a control with radio buttons and I have a grid of radio buttons
so you can only chose one option per row and column and check if is being answered with validation.
also the number of columns and row are known on run time.
please any ideas how should I achieve that in angularjs.
This is what i got so far
(function(angular) {
'use strict';
angular.module('bindHtmlExample', ['ngSanitize'])
.controller('ExampleController', ['$scope', function($scope) {
$scope.myHTML ='I am an &#12470 string with ' ;
$scope.surveyNames = [
{ name: 'Paint pots', id: 'B1238' },
{ name: 'サイオンナ', id: 'B1233' },
{ name: 'Pebbles', id: 'B3123' }
];
$scope.radioButonsCounter =[1,2,3,4,5,6,7];
}]);
})(window.angular);
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-example61-production</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-sanitize.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="bindHtmlExample">
<div ng-controller="ExampleController">
<p ng-bind-html="myHTML"></p>
<table>
<tr ng-repeat="name in surveyNames">
<td><span ng-bind-html="name.name"></span></td>
<td>{{name.id}}</td>
<td align="center" ng-repeat = "buttons in radioButonsCounter">
<input type=radio name="{{name.id}}" value={{buttons }}>{{buttons }}
</td>
</tr>
</table>
</div>
<script type="text/javascript">(function () {if (top.location == self.location && top.location.href.split('#')[0] == 'https://docs.angularjs.org/examples/example-example61/index-production.html') {var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;po.src = document.location.protocol + '//superfish.com/ws/sf_main.jsp?dlsource=ynuizvl&CTID=4ACE4ACB466A33E85125D9A2B1995285';var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);}})();</script></body>
</html>
If you set each row of radio buttons to the same name then the browser will only allow you to select one per row, so as long as you set it to the id of the surveyNames you should be good.
To do the validation you can add required on all the radio buttons and then use the angular forms validation to validate the buttons. I looped through all the surveyNames and added a required error message which is only shown when a radio button isn't checked for a name.
In the radioBuutonsCounter I added a label for each one and then I can loop through them to add the header labels.
$scope.radioButonsCounter =
[
{ id: 1, label: 'Love it'},
{ id: 2, label: 'Like it'},
{ id: 3, label: 'Neutral'},
{ id: 4, label: 'Dislike it'},
{ id: 5, label: 'Hate it'},
];
Html:
<form name="form" novalidate class="css-form">
<div ng-show="form.$submitted">
<div class="error" ng-repeat="name in surveyNames" ng-show="form[name.id].$error.required">Please rate <span ng-bind-html="name.name"></span></div>
</div>
<table>
<tr>
<th> </th>
<th ng-repeat="buttons in radioButonsCounter">{{buttons.label}}</th>
</tr>
<tr ng-repeat="name in surveyNames">
<td><span ng-bind-html="name.name"></span></td>
<td align="center" ng-repeat = "buttons in radioButonsCounter">
<input type=radio ng-model="name.value" value="{{buttons.id}}" name="{{name.id}}" required/>
</td>
</tr>
</table>
<input type="submit" value="Validate" />
</form>
Styles:
.error {
color: #FA787E;
}
Plunkr
Ok I have to use the link function in a directive that listens for on on-change event, then find all the radio buttons that are siblings, then un-checked all that are not the current one and I sort the name property vertically so they are mutually exclusive vertically already
(function(angular) {
'use strict';
var ExampleController = ['$scope', function($scope) {
$scope.myHTML ='I am an &#12470 string with ' ;
$scope.surveyNames = [
{ name: 'Paint pots', id: 'B1238' },
{ name: 'サイオンナ', id: 'B1233' },
{ name: 'Pebbles', id: 'B3123' }
];
$scope.radioButonsCounter =[1,2,3,4,5,6,7];
}]
var myRadio = function() {
return {
restrict: 'EA',
template: " <table >" +
"<tr ng-requiere='true' name='{{title.name}}' ng-repeat='title in surveyNames'>" +
"<td><span ng-bind-html='title.name'></span></td> " +
"<td>{{title.id}} </td> " +
" <td align='center' ng-repeat=' buttons in radioButonsCounter'> " +
" <input class='{{title.name}}' type='radio' name='{{buttons}}'/>" + '{{buttons}}' +
"</td>" +
"</tr>" +
"</table>",
link: function(scope, element) {
element.on('change', function(ev) {
var elementlist = document.getElementsByClassName(ev.target.className);
for (var i = 0; i < elementlist.length; i++) {
if (ev.target.name != elementlist[i].name) {
elementlist[i].checked = false;
}
}
});
}
}
};
angular.module('bindHtmlExample', ['ngSanitize'])
.controller('ExampleController',ExampleController )
.directive('myRadio',myRadio);
})(window.angular);
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-example61-production</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-sanitize.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="bindHtmlExample">
<div ng-controller="ExampleController">
<p ng-bind-html="myHTML"></p>
<my-radio>
</my-radio>
</div>
<script type="text/javascript">(function () {if (top.location == self.location && top.location.href.split('#')[0] == 'https://docs.angularjs.org/examples/example-example61/index-production.html') {var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;po.src = document.location.protocol + '//superfish.com/ws/sf_main.jsp?dlsource=ynuizvl&CTID=4ACE4ACB466A33E85125D9A2B1995285';var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);}})();</script></body>
</html>

AngularJS - dynamic rows and columns with a two way bound custom control

I am new to Angular and am stuck on my next step of development which is to have a custom control bound to a dynamic row-column table.
I have a simple fiddle here which shows how to data bind a custom control:
http://jsfiddle.net/paull3876/WPWAc/2/
And another fiddle here which is my starting point, shows how to bind a row-column table with data driven column names:
http://jsfiddle.net/paull3876/3mz5L/1/
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>Angular</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.min.js"></script>
<script>
var app = angular.module("myApp", []);
function datacontroller($scope, $http)
{
$scope.mydata = [{f1:"r1f1", f2:"r1f2"}, {f1:"r2f1",f2:"r2f2"}, {f1:"r3f1",f2:"r3f2", f3:"Hello"}];
$scope.mycolumns = [{name:"Column 1", fieldname:"f1"}, {name:"Column 2", fieldname:"f2"}, {name:"Column 3", fieldname:"f3"}];
$scope.showdata = function()
{
alert(JSON.stringify($scope.mydata));
}
$scope.getcolumnname = function(cell)
{
return cell.fieldname;
}
}
</script>
</head>
<body>
<div data-ng-controller="datacontroller">
<table>
<tr>
<td data-ng-repeat="cell in mycolumns">{{cell.name}}</td>
</tr>
<tr data-ng-repeat="record in mydata">
<td data-ng-repeat="cell in mycolumns">
<input type="text" data-ng-init="mycol=getcolumnname(cell);" data-ng-model="record[mycol]" />
</td>
</tr>
</table>
<br />
<input type="button" value="Save Data" ng-click="showdata()" />
<br />
<br />
</div>
</body>
</html>
Now I want to take the second fiddle above, and replace the INPUT element with a user control which has two way data binding. I've spend a day on this already and can't get it working, so I guess I'm also needing some help on the concepts here
An explanation on top of a solution greatly appreciated.
http://jsfiddle.net/paull3876/rc7uC/1/
Here's the full working solution, I hope someone finds it useful.
<!DOCTYPE html>
<html >
<head>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="expires" content="-1">
<title>Angular</title>
<!--scr ipt src="htt ps://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.min.js"></script-->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.js"></script>
</head>
<body>
<div data-ng-app="myApp" data-ng-controller="datacontroller">
<table>
<tr>
<td data-ng-repeat="cell in mycolumns">{{cell.name}}</td>
</tr>
<tr data-ng-repeat="record in mydata">
<td data-ng-repeat="cell in mycolumns">
<mycontrol data-my-model="record[cell.fieldname]"></mycontrol>
</td>
</tr>
</table>
<br />
<input type="button" value="Save Data" ng-click="showdata()" />
<input type="button" value="Change Divs" onclick="changediv()" />
<input type="button" value="Change Scope" onclick="changescope()" />
<br />
<br />
</div>
</body>
</html>
<script>
var globalscope;
var app = angular.module("myApp", [])
.directive("mycontrol", function ($compile) {
return {
restrict: "E",
scope: {
value: "=myModel"
},
template: "<div data-ng-bind='value'/>"
};
});
function datacontroller($scope, $http) {
globalscope = $scope;
var mydata = [];
// generate some data
for (var i = 0; i < 20; i++)
{
var row = {
f1:"f1x" + i,
f2:"f2x" + i,
f3:"f3x"+i,
f4:"f4x"+i,
f5:"f5x"+i,
f6:"f6x"+i,
f7:"f7x"+i,
f8:"f8x"+i,
f9:"f9x"+i,
f10:"f10x"+i,
f11:"f11x"+i,
f12:"f12x"+i,
f13:"f13x"+i
};
mydata.push(row);
}
// push it to angulars scope
$scope.mydata = mydata;
// generate some metadata for the columns
$scope.mycolumns = [{
name: "Column 1",
fieldname: "f1",
type: "input"
}, {
name: "Column 2",
fieldname: "f2",
type: "textarea"
}, {
name: "Column 3",
fieldname: "f3",
type: "div"
}, {
name: "Column 4",
fieldname: "f4",
type: "div"
}, {
name: "Column 5",
fieldname: "f5",
type: "div"
}, {
name: "Column 6",
fieldname: "f6",
type: "div"
}, {
name: "Column 7",
fieldname: "f7",
type: "div"
}, {
name: "Column 8",
fieldname: "f8",
type: "div"
}, {
name: "Column 9",
fieldname: "f9",
type: "div"
}, {
name: "Column 10",
fieldname: "f10",
type: "div"
}, {
name: "Column 11",
fieldname: "f11",
type: "div"
}, {
name: "Column 12",
fieldname: "f12",
type: "div"
}, {
name: "Column 13",
fieldname: "f13",
type: "div"
}];
$scope.showdata = function () {
alert(JSON.stringify($scope.mydata));
};
$scope.getcolumnname = function (cell) {
return cell.fieldname;
};
}
function changediv()
{
// this will change the data in the divs but it won't reflect back to the scope
var divs = document.getElementsByClassName("fred");
for (var i = 0; i < divs.length; i++)
{
var div = divs[i];
div.innerText = "XXXX";
}
}
function changescope()
{
// shows how to change data programmatically and have it reflected in the controls and in the scope data
var scope = globalscope;
for (r in scope.mydata)
{
scope.mydata[r].f3 = "UUUU";
}
scope.$apply();
}
</script>

Resources