Filter REST $resource data by $routeparams - angularjs

I am using Angular to populate a few pages with REST data and have a list of articles for which I want a link to show the article details for that article. Basically, I need to filter the REST call I use for an individual article by the routeparam that is passed to it.
It appears to be passing the routeparam as expected, but I am having some challenges getting the REST call to work on my details page (articles.html), and I suspect that I am not getting/matching the ID in my REST call to the ID passed by the routeparam. My first REST call works for the categories.html page which lists all articles. I am using Angular's ngResource API with $resource. Here is the applicable code:
app.js (routing)
var pfcModule = angular.module('pfcModule', ['ngRoute', 'pfcServices', 'pfcControllers']);
pfcModule.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/home', { templateUrl: './views/home.html'}).
when('/categories', { templateUrl: './views/categories.html', controller: 'pfcCtrl' }).
when('/articles/:articleID', { templateUrl: './views/articles.html', controller: 'pfcCtrl2' }).
otherwise({ redirectTo: '/home' });
}]);
services.js (REST Call)
var pfcServices = angular.module('pfcServices', ['ngResource'])
pfcServices.factory('pfcArticles', ['$resource',
function($resource){
return $resource('https://pfc.azure-mobile.net/tables/articles/:articleID', {});
}]);
controllers.js (Controllers)
var pfcControllers = angular.module('pfcControllers', []);
pfcControllers.controller('pfcCtrl', ['$scope', 'pfcArticles', function ($scope, pfcArticles) {
$scope.data = pfcArticles.query();
}]);
pfcControllers.controller('pfcCtrl2', ['$scope', '$routeParams', 'pfcArticles', function ($scope, $routeParams, pfcArticles) {
$scope.data2 = pfcArticles.get({ articleID: $routeParams.articleID });
}]);
categories.html (partial, working as expected)
<div class="row">
<div class="col-md-4">
<h2>Heading</h2>
<table class="table table-striped">
<tr>
<th>ID</th>
<th>Title</th>
<th>Category ID</th>
<th>Link</th>
</tr>
<tr ng-repeat="article in data">
<td>{{article.id}}</td>
<td>{{article.articletitle}}</td>
<td>{{article.articlecategoryid}}</td>
<td>Link</td>
</tr>
</table>
</div>
articles.html (partial, not working as I expect it to be filtered by the ID passed by the routeparam)
<div class="row">
<div class="col-md-4">
<h2>Heading</h2>
<table class="table table-striped">
<tr>
<th>ID</th>
<th>Title</th>
<th>Category ID</th>
<th>Summary</th>
</tr>
<tr ng-repeat="article in data2">
<td>{{article.id}}</td>
<td>{{article.articletitle}}</td>
<td>{{article.articlecategoryid}}</td>
<td>{{article.articlesummary}}</td>
</tr>
</table>
</div>

After some researching, I adjusted my articles.html partial to not have a repeat as follows, and it is working:
<div class="row">
<div class="col-md-4">
<h2>Heading</h2>
<table class="table table-striped">
<tr>
<th>ID</th>
<th>Title</th>
<th>Category ID</th>
<th>Summary</th>
</tr>
<tr>
<td>{{data2.id}}</td>
<td>{{data2.articletitle}}</td>
<td>{{data2.articlecategoryid}}</td>
<td>{{data2.articlesummary}}</td>
</tr>
</table>
</div>

Related

How to bind different scopes from one controller to the one?

I have a controller that I use in two places: in a ng-view and in a ng-include. These places are not child or parent to each other, but I want to some changes made in the ng-view affect to ng-include as well. How can I do that?
Here is plunker with these parts of code.
I want to when "Edit user" is clicked the user.userName from the table shows in the popup.
index.html
<body>
<div ng-view></div>
<div ng-include="'edit-user.html'"></div>
<script src="app.js"></script>
<script src="UsersController.js"></script>
</body>
app.js
var app = angular.module('myApp', ['ngRoute', 'ui.materialize'])
.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'users.html',
controller: 'UsersController'
})
.otherwise({redirectTo: '/'});
}]);
users.html
<h4>Users</h4>
<table class="striped highlight">
<thead>
<tr>
<th data-field="displayName">Display Name</th>
<th data-field="userName">User Name</th>
<th data-field="registered">Registered</th>
<th data-field="updated">Updated</th>
<th data-field="email">Email</th>
<th data-field="authority">Authority</th>
<th data-field="edit">Edit</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="user in users">
<td ng-bind="user.displayName"></td>
<td ng-bind="user.userName"></td>
<td ng-bind="user.registered"></td>
<td ng-bind="user.updated"></td>
<td ng-bind="user.email"></td>
<td ng-bind="user.authority"></td>
<td><a class="collection-item waves-effect waves-teal" modal open="openModal" ng-click="openModalFunc(user)">Edit user</a></td>
</tr>
</tbody>
</table>
<a data-target="edit-user" class="hide" modal open="openModal">Edit user</a>
UsersController.js
app.controller('UsersController', ['$scope', function($scope) {
// create fake users
$scope.users = [
{
displayName: 'Alexander',
registered: '02-07-2017',
updated: '02-07-2017',
email: 'alex#gmail.com',
authority: 'admin',
userName: 'Alex'
},
{
displayName: 'Lev',
registered: '02-07-2017',
updated: '02-07-2017',
email: 'lev#gmail.com',
authority: 'guest',
userName: 'Lev'
}
]
$scope.openModal = false;
$scope.openModalFunc = function(user) {
$scope.openModal = true;
$scope.selectedUser = user;
Materialize.toast('Awesome, we did it!', 4000);
}
}]);
edit-user.html
<div id="edit-user" class="modal col l3" ng-controller="UsersController">
<div class="modal-content">
<h4>{{selectedUser.userName}}</h4>
</div>
<div class="modal-footer">
<a class="modal-action modal-close waves-effect waves-green btn-flat">Agree</a>
</div>
</div>
If it is not very big application then you can use $broadcast from one controller and catch that using $on..
You can find more information here.
I've found that better solution is to move your data that need to be shared into the upper general scope.

Not able to sort using Smart Table in angularJS

I am using smart table but I am not able to sort the table, the following is my code
<div ng-app="app">
<div ng-controller="app-controller">
<table st-table="EmployeeDetails" class="table table-striped table-hover" st-safe-src="EmployeeData">
<thead>
<tr>
<th st-sort="EmployeeName">Employee Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="employee in EmployeeData">
<td class="col-xs-2">
<small>{{employee.EmployeeName}}</small>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<script type="text/javascript">
var app = angular.module('app', []);
app.controller('app-controller', ['$scope','$http', function ($scope,$http) {
$http.get('/Data/EmployeeDetails.json').success(function (data) {
$scope.EmployeeData = data;
}).error(function () {
alert('error');
});
}]);
</script>
can anyone let me know what exactly is wrong, i have referenced both angular.js and smart-table.js
<script src="../Scripts/angular.js"></script>
<script src="../Scripts/smart-table.js"></script>
You should use 'EmployeeDetails' at ng-repeat
JSFiddle
OK
<tr ng-repeat="employee in EmployeeDetails">
NG
<tr ng-repeat="employee in EmployeeData">
Thanks

Not showing data in HTML from Angular app

I'm consuming a Django REST API with an Angular JS app. I want to print a list of classrooms in a HTML table. This is the Json data I get from the REST API: http://pastebin.com/raw/s0knYX89
Here's the HTML
<div ng-app="userListApp">
<div ng-controller="UsersController">
<table class="table table-striped">
<thead>
<tr>
<th>Classroom</th>
<th>School</th>
<th>Academic year</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="classroom in classrooms">
<td>{{classroom.classroom}}</td>
<td>{{classroom.school.school_name}}</td>
<td>{{classroom.academic_year}}</td>
</tr>
</tbody>
</table>
</div>
</div>
And here's the app.js
var userListApp = angular.module('userListApp', ['ngResource']);
userListApp.factory('Classroom', function($resource) {
return $resource('/classrooms/?format=json', {}, {
query: {
method: 'GET',
isArray:true,
}
});
});
userListApp.controller('UsersController', function($scope, $resource, Classroom) {
Classroom.query({},function(data) {
$scope.classrooms = data;
console.log(data);
});
});
Anyway, all I get is this
I put console.log(data); to check if the data arrives to the page, and that's what I get: all of the data in the console, and none in the HTML page - even though the rows of the table are three, exactly the number I should get, but they are all blank.
Any thoughts?
As you can see in the console.log, the data returned is a promise. Try to access the api response correctly.
Try adding ng-show on the table:
<table ng-show = "classrooms != null" class="table table-striped">
<thead>
<tr>
<th>Classroom</th>
<th>School</th>
<th>Academic year</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="classroom in classrooms">
<td>{{classroom.classroom}}</td>
<td>{{classroom.school.school_name}}</td>
<td>{{classroom.academic_year}}</td>
</tr>
</tbody>
</table>
Where did you call a functnio to start $http request?

AngularJS - Show a form from a table row

I have a table with materials and when I click I want to show a form with all the data related to the row. What is the best approach to do that?
You can see my code below
index.html
<section ng-controller="materialController as materialCtrl">
<table class="table table-hover">
<th> Nombre </th>
<th> DescripciĆ³n </th>
<tr ng-repeat="material in materials" ng-click="materialCtrl.openForm()">
<td>
{{material.name}}
</td>
<td>
{{material.description}}
</td>
</tr>
</table>
</section>
Controller
app.controller("materialController", ["$scope", "$http", function($scope, $http){
$http.get('material').success(function(data){
$scope.materials = data;
});
this.openForm = function(){
// Do something
};
}]);
First, I think you could solve this by storing the material in some scope variable and using that to determine which row has been clicked. Second, you're doing this controller thing wrong and I will show you how to fix it. You're referencing the controller directly which is probably not the best practice. I suggest you change your code to look like this
app.controller("materialController", ["$scope", "$http", function($scope, $http){
$http.get('material').success(function(data){
$scope.materials = data;
});
$scope.selectedRow;
$scope.openForm = function(material){
$scope.selectedRow = material;
};
}]);
<!--reference controller directly -->
<section ng-controller="materialController">
<table class="table table-hover">
<th> Nombre </th>
<th> DescripciĆ³n </th>
<!-- reference openForm from scope -->
<tr ng-repeat="material in materials" ng-click="openForm(material)">
<td>
{{material.name}}
</td>
<td>
{{material.description}}
</td>
</tr>
</table>
</section>
then for each material if you have some form you want to show or anything else
<form ng-repeat="material in materials" ng-show="selectedRow == material">
Also, this isn't so important but more of a best practice, you should extract your http request into a service. https://docs.angularjs.org/guide/services

Ng-Click NOT working (Angular Datatables)

I have a problem with my angular datatables .
First, My code work very good, but after i add the code configure notSortable() for some colum , the ng-click of button is not working , and i can't fix it . Could you help me?
Here are my Code :
1> File index.html
<table datatable="ng" dt-options="dtOptions" dt-columns="dtColumns">
<thead>
<tr>
<th>ID</th>
<th>FirstName</th>
<th>LastName</th>
<th>Button</th>
</tr>
</thead>
<tbody>
<tr dt-rows ng-repeat="person in persons">
<td ng-bind="person.id"></td>
<td ng-bind="person.firstName"></td>
<td ng-bind="person.lastName"></td>
<td>
<input type="button" ng-click="doClick()">
</td>
</tr>
</tbody>
</table>
2>File app.js
(function(angular) {
'use strict';
angular.module('datatablesSampleApp', ['datatables']).
controller('simpleCtrl', function($scope, $http, DTOptionsBuilder, DTColumnBuilder) {
$scope.persons = [];
$http.get('data.json').success(function(persons) {
$scope.persons = persons;
});
$scope.doClick=function(){
alert("Clicked button !")
}
$scope.dtOptions = DTOptionsBuilder.newOptions().withPaginationType('full_numbers').withDisplayLength(40);
$scope.dtColumns = [
DTColumnBuilder.newColumn('id').withTitle('ID').notSortable(),
DTColumnBuilder.newColumn('firstName').withTitle('First name'),
DTColumnBuilder.newColumn('lastName').withTitle('Last name'),
DTColumnBuilder.newColumn('Button').withTitle('Button')
];
});
})(angular);
Don't use
<input type="button" ng-click="doClick()">
In stead of that try to use:
<button type="button" ng-click="doClick()">Send</button>
Be sure to specify the controller in your index.html with ng-controller='simpleCtrl'
I had the same issue, below is the solution that worked for me
**1. Step 1 is same , repeating for the sake of completeness**
<table datatable="ng" dt-options="dtOptions" dt-columns="dtColumns">
<thead>
<tr>
<th>ID</th>
<th>FirstName</th>
<th>LastName</th>
<th>Button</th>
</tr>
</thead>
<tbody>
<tr dt-rows ng-repeat="person in persons">
<td ng-bind="person.id"></td>
<td ng-bind="person.firstName"></td>
<td ng-bind="person.lastName"></td>
<td>
<input type="button" ng-click="doClick()">
</td>
</tr>
</tbody>
</table>
**Step2, In Controller, do the following**
(function(angular) {
'use strict';
angular.module('datatablesSampleApp', ['datatables']).
controller('simpleCtrl', function($scope, $http, DTOptionsBuilder, DTColumnBuilder) {
$scope.persons = []
$scope.init = function() {
$scope.dtOptions = DTOptionsBuilder.newOptions()
.withOption('aLengthMenu', [[-1], ['All']]) // Length of how many to show per pagination.
.withPaginationType('full_numbers')
.withBootstrap();
$http.get("data.json").then( function(result){
$scope.persons = result.data
});
}
$scope.init()
});
})(angular);

Resources