I am trying to give a table the ability to sort by all columns, but having a bit of trouble. I am pulling some data from a webservice to populate the table but then want to sort wherever the user wants. I have a plunker here. Of my close attempt. I was thinking something like this:
$scope.order = function(predicate, reverse) {
$scope.recentalerts = orderBy($scope.recentalerts, predicate, reverse);
};
like from the angular website might work, but am having a bit of trouble integrating it into my own table. What am I doing wrong? Or is there an easier way to do so? I'd like to just stick with plain angular like this example.
Your example is working (after fixing the plunkR), however you always force reverse to false.
If you want to reproduce what Angular do, which is inverse the reverse parameter on each click, you could for instance add somehting like this:
$scope.orders[predicate] = !$scope.orders[predicate];
$scope.recentalerts = orderBy($scope.recentalerts, predicate, $scope.orders[predicate]);
See working plunkr:
http://plnkr.co/edit/Z9LDlWvwWV82D65pfiF6?p=preview
Or in a simpler form, use a common $scope.reverse attribute:
http://plnkr.co/edit/sMD7ZqmsJ7bULa26jo6q?p=preview
Here's a snippet of what I use for rolling my own sorting in tables. Simply using a string to determine what property I want to sort by (with reverse supported) and changing it dynamically, then using orderBy on the ng-repeat.
Hope this helps.
angular.module('app', [])
.controller('testCtrl', ['$scope',
function($scope) {
$scope.sortBy = 'ID';
$scope.sort = function(sortBy) {
if ($scope.sortBy == sortBy) {
$scope.sortBy = '-' + sortBy
} else {
$scope.sortBy = sortBy;
}
}
$scope.people = [{
'ID': 1,
'Name': 'Aaron',
'Age': 70
}, {
'ID': 28,
'Name': 'Ben',
'Age': 60
}, {
'ID': 2,
'Name': 'Claire',
'Age': 50
}, {
'ID': 14,
'Name': 'Damian',
'Age': 40
}, {
'ID': 8,
'Name': 'Frank',
'Age': 30
}];
}
]);
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.css" rel="stylesheet"/>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-app="app">
<div ng-controller="testCtrl">
<div id="wrapper">
<div style="margin: 1em">
<h4>Recent Alerts</h4>
<div>
<table class="table table-hover table-striped">
<thead>
<tr>
<th ng-click="sort('ID')">ID
<i class="fa fa-caret-down" ng-show="sortBy=='-ID'"></i>
<i class="fa fa-caret-up" ng-show="sortBy=='ID'"></i>
</th>
<th ng-click="sort('Name')">Name
<i class="fa fa-caret-down" ng-show="sortBy=='-Name'"></i>
<i class="fa fa-caret-up" ng-show="sortBy=='Name'"></i>
</th>
<th ng-click="sort('Age')">Age
<i class="fa fa-caret-down" ng-show="sortBy=='-Age'"></i>
<i class="fa fa-caret-up" ng-show="sortBy=='Age'"></i>
</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="person in people | orderBy: sortBy">
<td ng-bind="person.ID"></td>
<td ng-bind="person.Name"></td>
<td ng-bind="person.Age"></td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- /.col-lg-12 -->
</div>
</div>
</body>
</html>
Related
I am trying to filter a Javascript dictionary based on multiple conditions.
I tried doing these steps:
I created an empty dictionary variable
Selected the input element and get the raw HTML node
Saved the value of the element that was changed as a variable
Saved the id of the element that was changed as another variable
conditionally add values to the filters object
// 1. Create a variable to keep track of all the filters as an object.
var filters = {};
// 3. Use this function to update the filters.
function updateFilters() {
// 4a. Save the element that was changed as a variable.
let changedElement = d3.select(this);
// 4b. Save the value that was changed as a variable.
let elementValue = changedElement.property("value")
console.log(elementValue);
// 4c. Save the id of the filter that was changed as a variable.
let filterId = changedElement.attr("id");
console.log(filterId);
// 5. If a filter value was entered then add that filterId and value
// to the filters list. Otherwise, clear that filter from the filters object.
if (elementValue != "") {
filters[filterId] = elementValue;
}
else {
delete filters[filterId];
}
// 6. Call function to apply all filters and rebuild the table
filterTable();
In the next function I need to loop through the filters list and keep data that matches the filter values.
// 7. Use this function to filter the table when data is entered.
function filterTable() {
// 8. Set the filtered data to the tableData.
let filteredData = tableData;
// 9. Loop through all of the filters and keep any data that
// matches the filter values
Object.entries(filters).forEach(([filterId, elementValue]) => {
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.datetime === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.city === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.state === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.country === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.shape === elementValue);
}
};
// 10. Finally, rebuild the table using the filtered data
buildTable(filteredData);
}
// 2. Attach an event to listen for changes to each filter
d3.selectAll("input").on("change", updateFilters);
// Build the table when the page loads
buildTable(tableData);
The interface looks like this:
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- <meta http-equiv="X-UA-Compatible" content="IE=edge"> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/superhero/bootstrap.min.css"> -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<title>UFO Finder</title>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous"
/>
<link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
<link rel="stylesheet" href="static/css/style.css">
</head>
<body class="bg-dark">
<div class="wrapper">
<nav class="navbar navbar-dark bg-dark navbar-expand-lg">
<a class="navbar-brand" href="index.html">UFO Sightings</a>
</nav>
<div class="jumbotron">
<h1 class="display-4">The Truth Is Out There</h1>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-4">
<h3>UFO Sightings: Fact or Fancy? <small>Ufologists Weigh In</small></h3>
</div>
<div class="col-md-8">
<p>Some Text</p>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<form class="bg-dark">
<p>Filter Search</p>
<ul class="list-group bg-dark">
<li class="list-group-item bg-dark">
<label for="date">Enter Date</label>
<input type="text" placeholder="1/10/2010" id="datetime"/>
</li>
<li class="list-group-item bg-dark">
<label for="city">Enter a City</label>
<input type="text" placeholder="roswell" id="city">
</li>
<li class="list-group-item bg-dark">
<label for="state">Enter a State</label>
<input type="text" placeholder="ca" id="state">
</li>
<li class="list-group-item bg-dark">
<label for="Country">Enter a Country</label>
<input type="text" placeholder="us" id="country">
</li>
<li class="list-group-item bg-dark">
<label for="Shape">Enter a Shape</label>
<input type="text" placeholder="crcle" id="shape">
</li>
<!-- <li class="list-group-item bg-dark">
<button id="filter-btn" type="button" class="btn btn-dark" >Clear Table</button>
</li> -->
</ul>
</form>
</div>
<div class="col-md-9">
<table class="table table-striped">
<thead>
<tbody>
<tr>
<th>Date</th>
<th>City</th>
<th>State</th>
<th>Country</th>
<th>Shape</th>
<th>Duration</th>
<th>Comments</th>
</tr>
</tbody>
</thead>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.js"></script>
<script type="text/javascript" src="./static/js/data.js"></script>
<script type="text/javascript" src="./static/js/ufo_starterCode.js"></script>
</body>
</html>
data.js
var data = [
{
datetime: "1/1/2010",
city: "benton",
state: "ar",
country: "us",
shape: "circle",
durationMinutes: "5 mins.",
comments: "4 bright green circles high in the sky going in circles then one bright green light at my front door."
},
{
datetime: "1/1/2010",
city: "bonita",
state: "ca",
country: "us",
shape: "light",
durationMinutes: "13 minutes",
comments: "Three bright red lights witnessed floating stationary over San Diego New Years Day 2010"
}
];
The goal is to be able to filter records in a table based on the filter search criteria entered by the user.
Please note that I'm very new to Javascript. Any help is appreciated.
As you are new to JavaScript I would recommend that you start with the basics. And that means: try and leave out libraries and frameworks as much as possible. In the following snippet I removed your references to bootstrap, D3, datatables and jQuery as they are not really needed to solve the basic problem of filtering your table. This is also a requirement for posting code here in SO. You should always try to provide an "MCVE" (a minimum complete and viable example).
I chose a very basic concept for the filtering: Seeing that the input fields correspond directly to the first five columns of your table I applied the trick of going through the values of all theses inputs and compare them to the corresponding table values. These values are found by doing a forEach() loop over the table rows (<tr>) and then making sure that I get a "positive match" for the first five <td>s ([...tr.children].slice(0,5)) of each row. The text comparison is made between the lower-case version of each inp.value (stored in vals[I]) and the corresponding td.textContent, but only, if vals[i] is not empty (otherwise a positive match is returned, as an empty vals[i] means that there is no filtering for that column in place). So, if all five columns (.every()-loop) fulfil the "matching" condition the .style.display property for the current <tr> is set to "", otherwise to "none".
const data = [
{ datetime: "1/1/2010", city: "benton", state: "ar", country: "us", shape: "circle", durationMinutes: "5 mins.",
comments: "4 bright green circles high in the sky going in circles then one bright green light at my front door." },
{ datetime: "1/1/2010", city: "bonita", state: "ca", country: "us", shape: "light", durationMinutes: "13 minutes",
comments: "Three bright red lights witnessed floating stationary over San Diego New Years Day 2010" },
{ datetime: "1/13/2010", city: "Bonita", state: "ca", country: "us", shape: "square", durationMinutes: "3 minutes",
comments: "Early in January we saw a blue square appear right out of nowhere." }];
// fill table:
const tb=document.querySelector("table tbody");
tb.innerHTML=
data.map(r=>"<tr><td>"+Object.values(r).join("</td><td>")+"</td></td>").join("\n");
// filter table:
const inps=[...document.querySelectorAll("ul input")];
document.querySelector("ul").addEventListener("input",ev=>{
const vals=inps.map(inp=>inp.value.toLowerCase());
// filter table according to content of first 5 columns:
[...tb.children].forEach(tr=> // check for every table record:
tr.style.display=[...tr.children].slice(0,5).every((td,i)=>
vals[i]==="" || td.textContent.toLowerCase().includes(vals[i])
) ? "" : "none"
// show record if vals[i]==="" or if vals[i] is part of the corresponding column contents
)
})
.table-striped tbody tr:nth-child(odd) {background-color:#ddd}
<div class="wrapper">
<div class="jumbotron">
<h1 class="display-4">The Truth Is Out There</h1>
</div>
<div class="container-fluid">
<div class="row">
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<form class="bg-dark">
<p>Filter Search</p>
<ul class="list-group bg-dark">
<li class="list-group-item bg-dark">
<label for="date">Enter Date</label>
<input type="text" placeholder="1/10/2010" id="datetime" />
</li>
<li class="list-group-item bg-dark">
<label for="city">Enter a City</label>
<input type="text" placeholder="roswell" id="city">
</li>
<li class="list-group-item bg-dark">
<label for="state">Enter a State</label>
<input type="text" placeholder="ca" id="state">
</li>
<li class="list-group-item bg-dark">
<label for="Country">Enter a Country</label>
<input type="text" placeholder="us" id="country">
</li>
<li class="list-group-item bg-dark">
<label for="Shape">Enter a Shape</label>
<input type="text" placeholder="crcle" id="shape">
</li>
<li class="list-group-item bg-dark">
<button id="filter-btn" type="button" class="btn btn-dark">Clear Table</button>
</li>
</ul>
</form>
</div>
<div class="col-md-9">
<table class="table table-striped">
<thead>
<tr>
<th>Date</th>
<th>City</th>
<th>State</th>
<th>Country</th>
<th>Shape</th>
<th>Duration</th>
<th>Comments</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
The original code was trying to filter the data object while looping through the filters; The code implementation below loops through the filters object while looping through the data object.
Since I would always have more rows than filters, I ran the .filter method once rather than per filter as I initially tried to do.
// 9. Loop through all of the filters and keep any data that matches the filter values
let filteredData = tableData.filter((obj) => {
for(filterId in filters) {
if(obj[filterId] !== filters[filterId]) {
return false;
}
}
return true;
});
I have table and i show data, with dynamic columns and data. As input data i have an array of values
here is my plunker
angular.module('plunker', ['ngMaterial','md.data.table'])
.config(['$mdThemingProvider', function ($mdThemingProvider) {
'use strict';
$mdThemingProvider.theme('default')
.primaryPalette('blue');
}])
.controller('MainCtrl', function($scope) {
var vm = $scope;
vm.test = '123';
vm.query = {
order: 'starttime',
limit: 25,
page: 1
};
vm.tabQuery = {
limit: 2,
page: 1
};
vm.data = {
"title": "Summary Reports -> manipulate",
"content": [
[
"a1s2",
"1"
],
[
"aaa",
"1"
],
[
"ccc",
"1"
],
[
"eee",
"1"
],
[
"ggg",
"1"
],
[
"iii",
"1"
],
[
"kkk",
"1"
],
[
"mmm",
"1"
],
[
"ooo",
"1"
],
[
"qqq",
"1"
],
[
"sss",
"1"
]
],
"columns": [
"name1",
"name2"
],
"transactionLogId": 432903
};
$scope.name = 'Plunker';
});
[ng\:cloak],
[ng-cloak],
[data-ng-cloak],
[x-ng-cloak],
.ng-cloak,
.x-ng-cloak {
display: none !important;
}
h1,
p {
font-family: sans-serif;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="lib/style.css" />
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.9/angular.min.js"></script>
<link rel="stylesheet" href="https://rawgit.com/daniel-nagy/md-data-table/master/dist/md-data-table.css">
</head>
<body ng-app="plunker" ng-cloak>
<div ng-controller="MainCtrl">
<md-toolbar class="md-table-toolbar md-default">
<div class="md-toolbar-tools" layout-align="end center">
<span class="md-subhead">Summary Report</span>
<div flex></div>
</div>
</md-toolbar>
<md-table-container md-scroll-y layout-fill layout="column" class="md-padding">
<table class="md-table" md-table md-progress="promise" style="font-size: 11px !important;">
<thead md-head>
<tr md-row>
<th md-column ng-repeat="col in data.columns track by $index"> {{ col }}</th>
</tr>
</thead>
<tbody md-body>
<tr md-row ng-repeat="val in data.content track by $index">
<td ng-repeat="el in val track by $index" md-cell ng-bind="el"></td>
</tr>
</tbody>
</table>
</md-table-container>
<md-table-pagination md-limit="3" md-boundary-links="true" md-limit-options="[5, 10, 15]" md-page="tabQuery.page" md-total="{{(data.content).length}}"></md-table-pagination>
</div>
<script src="lib/script.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.9/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.9/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.2.2/angular-material.min.js"></script>
<script src="https://rawgit.com/daniel-nagy/md-data-table/master/dist/md-data-table.js"></script>
</body>
</html>
My pagination via array of array doesn't works in this table.
I'm also tried add this part to ng-repeat:
"| limitTo: query.limit : (query.page -1) * query.limit"
The problem is: there is a table in AngularJS, there are, for example, 2 columns (maybe 5 and 10, they are dynamic) and also dynamic data, I bring an array for these columns into the table, for example I took 2 columns and 11 records, brought them into the table and made them the table showed 3 items, but it shows all 11 and pagination does not seem to rob, can anyone pushed with this?
Solved, I've added | limitTo: query.limit : (query.page -1) * query.limit to <td ng-repeat="el in val track by $index" md-cell>{{ el }}</td> and deleted ng-bind="el" (changed to {{ el }}) now it works as expect
Hi I am using angularjs ui bootstrap accordion. Here i want to call when user click on accordion call one function and get user
Here is the code please help me thnks in advance
$scope.load_userdata= function(user_id) {
console.log(user_id);
}
<uib-accordion close-others="oneAtATime">
<div uib-accordion-group class="panel-default" ng-repeat="user in users">
<uib-accordion-heading ng-click="load_userdata(user.id)">
<div class="table">
<div style="width: 50%">
#{{user.name}}
</div>
<div>
Load user data
</div>
</div>
</uib-accordion-heading>
</div>
</uib-accordion>
data and display it
I don't really understand what the problem is. I copied your template in the snippet below and added a simple controller with a working example.
The angular-bootstrap module is not included so you don't get the proper rendering. But it shows you how to define the function in your controller for your template to work.
function ctrl($scope) {
// dummy users data for the snippet purpose
$scope.users = [{
name: 'Joe',
id: '1',
data : 'Married to Jane',
},
{
name: 'John',
id: '2',
data : 'Has 3 children',
},
{
name: 'Jack',
id: '3',
data : 'Owns a boat',
},
{
name: 'Bob',
id: '4',
data : 'Speaks swedish',
}
];
$scope.load_userdata = function(user_id) {
console.log("Loading user#%s data", user_id);
// looking for the right user :
let user = $scope.users.find(x => x.id === user_id);
// and toggling the dataLoaded property in the user object
user.dataLoaded = true;
}
}
<!DOCTYPE html>
<html ng-app>
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.5/angular.min.js"></script>
<meta charset=utf-8 />
<title>Angular JS Demo</title>
</head>
<body ng-controller="ctrl">
<uib-accordion close-others="oneAtATime">
<div uib-accordion-group class="panel-default" ng-repeat="user in users">
<uib-accordion-heading ng-click="load_userdata(user.id)">
<div class="table">
<div style="width: 50%">
#{{user.name}}
</div>
<div>
Load user data
</div>
</div>
</uib-accordion-heading>
<div ng-show="user.dataLoaded">
User's details :
{{user.data}}
</div>
</div>
</uib-accordion>
</body>
</html>
im struggling with iterating over arrays in arrays. I need to create buttonlike vertical menu and cant get it work.
angular.module('NavigationApp',[]).controller('NavigationController', function($scope) {
$scope.items = [
'Home',
'Orders':
{
orders:['Orders', 'Open', 'Closed', 'New', 'Forgotten']
},
'Users',
'Resources',
'Settings',
'Help'
];
$scope.activeMenu = $scope.items[0];
$scope.setActive = function(item) {
$scope.activeMenu = item;
};
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body ng-app="NavigationApp">
<div class="col-md-3">
<div ng-controller="NavigationController">
<input type="text" placeholder="Search" ng-model="filterQuery" />
<ul class="list-group">
<li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items | filter:filterQuery">{{ item }}
</li>
</ul>
</div>
</div>
<script src="js/MainController.js"></script>
</body>
</html>
What i need to do is display array of items and while Orders item is active expand it with elements given in other array. To be honest i just dont know how to make it.
You are trying to ng-repeat over a heterogeneus array. i.e. it's elements are not all of the same type. The implementation logic needs to change here.
One thing you can do if your data structure is not flexible, is to use a typeof item === 'object' to filter out the object from the strings, or conversely check for typeof string
Here's a quick, basic example of what you could use:
$scope.items = [{
name: 'Home'
}, {
name: 'Orders',
dropdown: [{
name: 'Orders'
}]
},{
name: 'Users'
},
...
];
<li ng-repeat="item in items | filter:filterQuery" class="btn btn-lg list-group-item dropdown" ng-class="{active: activeMenu === item}" ng-click="setActive(item)">
<a aria-expanded="false" aria-haspopup="true" role="button" data-toggle="dropdown" class="dropdown-toggle" href="#">
{{ item.name }} <span class="caret" ng-if="item.dropdown"></span>
</a>
<ul ng-if="item.dropdown" class="dropdown-menu">
<li ng-repeat="dItem in item.dropdown">
{{dItem.name}}
</li>
</ul>
</li>
I'd suggest having another indepth look at https://docs.angularjs.org/api/ng/directive/ngRepeat to fully understand the structure required by the directive.
angular.module('NavigationApp',[]).controller('NavigationController', function($scope) {
$scope.items = {
main:['Home','Orders','Users','Resources','Settings','Help'],
sub:['Open','Closed','New','Forgotten']
};
$scope.activeMenu = $scope.items[0];
$scope.setActive = function(item) {
$scope.activeMenu = item;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body ng-app="NavigationApp">
<div class="col-md-3">
<div ng-controller="NavigationController">
<input type="text" placeholder="Search" ng-model="filterQuery" />
<ul class="list-group">
<li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items.main | filter:filterQuery">{{ item }}
<ul>
<li class="btn btn-lg list-group-item" ng-repeat="it in items.sub" ng-if="activeMenu === 'Orders'">{{it}}</li>
</ul>
</li>
</ul>
</div>
</div>
<script src="js/MainController.js"></script>
</body>
</html>
This is closer to what i want to achieve. But i dont know how to apply this nested UL to only one Li from parent list.
this filter work correctly
INPUT :
['Home',{ 'Orders':{orders:['Orders', 'Open', 'Closed', 'New', 'Forgotten']}},'Users','Resources','Settings','Help']
OUTPUT :
["Home", "Orders", "Open", "Closed", "New", "Forgotten", "Users", "Resources", "Settings", "Help"]
app.filter('customfilter', function () {
return function (data) {
function clean(item)
{
var result = [] ;
// check if type is array
if(Array.isArray(item)){
// parse array
item.forEach(function(i){
result = result.concat(clean(i));
})
}// check if type is opject
else if(typeof item =="object"){
// parse opject
Object.keys(item).map(function (key) {
result = result.concat(clean(item[key]));
});
}else{
result= [item]
}
return result ;
}
return clean(data) ;
}
})
I believe there are so many ways to answer this question,although I've made a sample plunker for your problem.Below is how your
HTML will look like
<body ng-app="NavigationApp">
<div class="col-md-3">
<div ng-controller="NavigationController">
<input type="text" placeholder="Search" ng-model="filterQuery" />
<ul class="list-group">
<li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items | filter:filterQuery">
<a href="#">
<p ng-hide="item.dropdown"> {{ item.name }}</p>
<p ng-show="item.dropdown" ng-repeat="values in item.dropdown"> {{ values }}</p>
</a>
</li>
</ul>
</div>
</div>
</body>
JS look like
angular.module('NavigationApp', []).controller('NavigationController', function($scope) {
var orderItemsObj = {
orders: ['Orders', 'Open', 'Closed', 'New', 'Forgotten']
};
$scope.items = [{
name: 'Home'
}, {
name: 'Orders',
dropdown: ['Orders', 'Open', 'Closed', 'New', 'Forgotten']
}, {
name: 'Users'
}, ];
$scope.activeMenu = $scope.items[0];
$scope.setActive = function(item) {
$scope.activeMenu = item;
};
});
I have a large json file almost 5 MB in size with the following array format.
There are about 3000 records.
I am using microsoft mvc 4 and angular + ngTable to display this data in the front end. It needs to be searchable and sortable on all columns.
The server side code does not take any arguments and returns all 3000 records in the format below.
{
"MR": "Inact",
"EncType": null,
"ClientAlias": 111020.0,
"OrgName": "Zic",
"CharacterAlias": null,
"Account#": 30645147.0,
"MRN": null,
"PlanCode": null,
"Address": "PO Box 123456",
"City": "Richmond ",
"St": "VA",
"ZIP": 23298.0,
"ContactName": "Jonny J",
"Fax": "(111) 111-1111",
"PHONE": "pager 111-1111",
"CriticalValueNotification": null,
"ClientPracticeTesting": null,
"Doctor": "John Smith",
"BeginDate": 36395.0,
"medBeginDate": null
}
The javascript file (app.js) contains the following code.
I have a separate files for the views as shown in the angular code below.
For ease of understanding the question, I have put everything in one snippet below.
var flexTable = angular.module("flexTable", ["ngRoute", "ngTable", "ngResource"]);
flexTable.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/about', {
templateUrl: '../../about.html',
controller: 'tableController'
})
.when('/contact', {
templateUrl: '../../contact.html',
controller: 'tableController'
})
.when('/', {
templateUrl: '../../table.html',
controller: 'tableController'
})
.when('/table', {
templateUrl: '../../table.html',
controller: 'tableController'
})
.otherwise({
redirectTo: '/table'
});
}]);
flexTable.controller('tableController',['$scope', '$resource' ,'ngTableParams', function ($scope, $resource,ngTableParams) {
var data = '';
var api = $resource("/Home/GetData")
$scope.tableParams = new ngTableParams({}, {
getData: function (params) {
var varApiGet = api.get(params.url()).$promise.then(function (data) {
params.total(data.inlineCount);
return data.results;
});
return varApiGet;
}
});
}]);
The html page looks as follows
<%# Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta name="viewport" content="width=device-width" />
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<link href="../../Assets/css/justified-nav.css" rel="stylesheet" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<link href="../../Assets/css/ng-table.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.3/angular-sanitize.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.3/angular-resource.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.3/angular-route.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.3/angular-animate.js"></script>
<script src="../../Assets/js/lib/ng-table.min.js"></script>
<script src="../../Assets/js/app.js"></script>
</head>
<body>
<div class="container" >
<!-- The justified navigation menu is meant for single line per list item.
Multiple lines will require custom code not provided by Bootstrap. -->
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>Default</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="jumbotron">
<h1>Instructions stuff!</h1>
<p class="lead">Cras justo odio, dapibus ac facilisis in, egestas eget quam.
Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh,
ut fermentum massa justo sit amet.</p>
<!--<p><a class="btn btn-lg btn-success" href="#" role="button">Get started today</a></p>-->
</div>
<div class="container" ng-controller="tableController">
<div ng-view>
<div class="row">
<table ng-table="tableParams" class="table">
<tr ng-repeat="row in $data track by $index">
<td title="'EncType'">
{{row.EncType}}
</td>
<td title="'ClientAlias'">
{{row.ClientAlias}}
</td>
<td title="'OrgName'">
{{row.OrgName}}
</td>
<td title="'CharacterAlias'">
{{row.CharacterAlias}}
</td>
<td title="'AddressCity'">
{{row.AddressCity}}
</td>
<td title="'St'">
{{row.St}}
</td>
<td title="'ZIP'">
{{row.ZIP}}
</td>
<td title="'ContactName'">
{{row.ContactName}}
</td>
<td title="'Fax'">
{{row.Fax}}
</td>
<td title="'PHONE'">
{{row.PHONE}}
</td>
<td title="'CriticalValueNotification'">
{{row.CriticalValueNotification}}
</td>
<td title="'Doctor'">
{{row.Doctor}}
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<footer class="footer">
<p>© 2015 Company, Inc.</p>
</footer>
</div><!--container-->
</body>
</html>
When I have the data hardcoded in the javascript controller function, the table displays fine without the search and sort functionality. When I have the data come in through the ajax call as shown in the code, it displays no data. only the table heading.
I can answer any questions that anyone has about this.
Thanks,
Paras
Any help appreciated.
EDIT
Here is the controller code that worked for me. I also added some extra code for the sorting and the filters.
flexTable.controller('tableController', ['$scope', '$http', 'ngTableParams', '$filter', '$log'
, function ($scope, $http, ngTableParams, $filter, $log) { //
$http.get('/Home/GetData')
.success(function (data, status) {
$scope.data = data;
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
OrganizationName: 'asc' // initial sorting
}
}
, {
total: $scope.data.length, // length of data
getData: function ($defer, params) {
// use build-in angular filter
var filterData = params.filter() ?
$filter('filter')($scope.data, params.filter()) :
$scope.data;
var orderedData = params.sorting() ?
$filter('orderBy')(filterData, params.orderBy()) :
filterData;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
}
);
});
}]);
You could use $http instead of $resource. Your response data will be in the data property of your response. Try the following:
$scope.tableParams = new ngTableParams({}, {
getData: function(params) {
var varApiGet = $http.get(params.url()).then(function(response) {
var data = response.data;
params.total(data.inlineCount);
return data.results;
});
return varApiGet;
}
});
Edit
Here is a working fiddle. I simulated the response as an array with one entry (the one you posted in the question). Make sure that your response data is in the correct format.