angularjs > router resolve > "Error: [$injector:unpr] Unknown provider" - angularjs

im trying to add a resolve\promise to my project, so when you ask for a page it will load up only after receiving the json from the server.
this is my js code:
'use strict';
angular.module('myApp.show', ['ngRoute'])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/show', {
templateUrl: 'views/show.html',
controller: 'showCtrl',
resolve: {
booksList: function ($http) {
return ($http.get('data/books.json')
.then(function (data) {
return data;
}));
}
}
});
}])
.controller('showCtrl', ['booksList', '$scope', function (booksList, $scope) {
$scope.books = booksList;
$scope.removeRow = function (productIndex) {
if (window.confirm("are you sure?")) {
$scope.books.splice(productIndex, 1);
}
}
}])
but this is what i get:
Error: [$injector:unpr] Unknown provider: booksListProvider <- booksList <- showCtrl
i kinda new to angular, but i followed several tutorials and while it worked in the video - i keep getting errors.
html:
<div class="table-responsive">
<div ng-app="myApp.show" ng-controller="showCtrl"> <!-- ctrl -->
<table st-table="rowCollection" class="table table-striped">
<thead>
<tr>
<th st-sort="author">Author</th>
<th st-sort="date">Date</th>
<th st-sort="title">Title</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(bookIndex, book) in books">
<td class="col-md-3">{{ book.author }}</td>
<td class="col-md-3">{{ book.date | date }}</td>
<td class="col-md-4">{{ book.title | beutifyTitle }}</td>
<td class="col-md-1"><ng-include src="'views/partials/editBook.html'"></ng-include></td>
<td class="col-md-1"><button class="btn btn-warning" ng-click="removeRow()">Delete</button></td>
</tr>
</tbody>
</table>
</div>
</div

You should be removing ng-controller="showCtrl" from your template. The reason being is, you are assing showCtrl via router already. But as you are again wrote ng-controller over inline template in that case it fails to get booksList resolve provider.

Related

Data from Angular $http request through asp.net api not getting to the DOM

So I have been able to confirm that data is getting into my angular function, but have been banging my head against the wall trying to get it to the DOM. I am doing everything as simple as I can before I start creating my full crud.
I'm sure I am missing something simple, as I am a newb with Angular and most certainly utilizing $http through asp.net api.
(function () {
angular
.module('appmodule')
.controller('campaignservice', ['$scope', '$http', campaignservice])
function campaignservice($scope, $http) {
$http.get("http://localhost:58291/api/campaigns").then(function (data) {
$scope.campaigns = data;
});
};
})();
and then the html
<div>
<div ng-controller="campaignservice">
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Pages </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="campaign in campaigns">
<td>{{campaign.Id}}</td>
<td>{{campaign.Name}}</td>
<td>{{campaign.Pages}}</td>
</tr>
</tbody>
</table>
</div>
Whats my deal?? My brain is bleeding.
From help in the comments I merely needed to make the following amendment.
$scope.campaigns = data.data;

Using AngularJS, how can I match items from two separate ng-repeats?

Using AngularJS, I am creating a table that is pulling data with two web requests.
Each web request has it's own ng-repeat in the HTML, ng-repeat="user in users" and ng-repeat="app in apps". Right now all existing apps are showing in every repeat of user. What I'd like to do is some kind of match, lookup, or filter and only show apps that the user is associated with. So, when user.Title == app.Title.
Here is the HTML:
<div ng-app="myApp">
<div ng-controller="MainCtrl">
<div class="ProfileSheet" ng-repeat="user in users">
<h3 class="heading">User Profile</h3>
<table id="Profile">
<tr>
<th>User</th>
<td>{{user.Title}}</td>
</tr>
<tr>
<th>First Name</th>
<td>{{user.FirstName}}</td>
</tr>
<tr>
<th>Last Name</th>
<td>{{user.LastName}}</td>
</tr>
<tr>
<th>Job Title</th>
<td>{{user.JobTitle}}</td>
</tr>
<tr>
<th>Emp ID</th>
<td>{{user.EmployeeID}}</td>
</tr>
<tr>
<th>Officer Code</th>
<td>{{user.OfficerCode}}</td>
</tr>
<tr>
<th>Email</th>
<td>{{user.Email}}</td>
</tr>
<tr>
<th>Telephone</th>
<td>{{user.WorkPhone}}</td>
</tr>
<tr>
<th>Fax Number</th>
<td>{{user.WorkFax}}</td>
</tr>
<tr>
<th>Location Description</th>
<td>{{user.LocationDescription}}</td>
</tr>
<tr>
<th>Mailstop / Banking Center #</th>
<td>{{user.Mailstop}}</td>
</tr>
</table>
<br>
<h3 class="heading">User Applications</h3>
<div style="border:3px solid #707070; padding-right:12px;">
<h4 style="padding-left:5px;">User Applications</h4>
<table id="Apps">
<tr id="AppsHeading">
<th>Application</th>
<th>User ID</th>
<th>Initial Password</th>
<th>Options / Comment</th>
<th>Setup Status</th>
</tr>
<tr ng-repeat="app in apps">
<td>{{app.Application.Title}}</td>
<td>{{app.Title}}</td>
<td>{{app.InitialPassword}}</td>
<td>{{app.OptionsComments}}</td>
<td style="border-right:3px solid #707070;">{{app.SetupStatus}}</td>
</tr>
</table>
</div>
</div>
</div>
The JS:
var app = angular.module('myApp', ['ngSanitize']);
var basePath = "https://portal.oldnational.com/corporate/projecthub/anchormn/associates"
app.controller('MainCtrl', function($scope, $http, $q){
var supportList;
$(document).ready(function() {
$scope.getAdminList();
$scope.getAppsList();
});
// $scope.selectedIdx = -1;
// $scope.showResults = false
$scope.prepContext = function(url,listname,query){
var path = url + "/_api/web/lists/getbytitle('" + listname + "')/items" + query;
console.log(path);
return path;
}
$scope.getAdminList = function() {
supportList = $http({
method: 'GET',
url: this.prepContext(siteOrigin+"/corporate/projecthub/anchormn/associates","User Administration","?$orderBy=LastName"),
headers: {
"Accept": "application/json; odata=verbose"
}
}).then(function(data) {
//$("#articleSection").fadeIn(2000);
console.log("adminlist", data.data.d.results);
$scope.users = data.data.d.results;
});
};
$scope.getAppsList = function() {
supportList = $http({
method: 'GET',
// url: this.prepContext(siteOrigin+"/corporate/projecthub/anchormn/associates","User Applications","?$select=Title,InitialPassword,OptionsComments,SetupStatus,Application/Title&$orderBy=Application&$expand=Application"),
url: this.prepContext(siteOrigin+"/corporate/projecthub/anchormn/associates","User Applications","?$select=Title,InitialPassword,OptionsComments,SetupStatus,Application/Title,ParentUserLink/ID&$orderBy=Application&$expand=Application,ParentUserLink"),
headers: {
"Accept": "application/json; odata=verbose"
}
}).then(function(data) {
//$("#articleSection").fadeIn(2000);
console.log("appslist", data.data.d.results);
$scope.apps = data.data.d.results;
});
};
});
app.config([
'$compileProvider',
function($compileProvider){
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrom-extension|javascript):/)
}
]);
How can I do this?
There's a lot of extraneous code in the controller. For the purposes of this answer I removed it. Also I understand that users and apps are related by a property called Title but the name was confusing me - forgive me if the data doesn't make sense.
Suggestion: Only use $(jQuery) where strictly necessary. Angular provides a lot of functionality that replaces jQuery functionality. Instead of using $.ready like:
$(document).ready(function() {
$scope.getAdminList();
$scope.getAppsList();
});
wait to bootstrap your application until the document is ready using the following code:
(function () {
angular.element(document).ready(function () {
angular.bootstrap(document, ['myApp']);
});
})();
Then you don't have to burden the controller with the responsibility of waiting until the document is loaded. Note: ng-app was removed from the markup.
Suggestion: Use $q.all() to wait for multiple promises to resolve. $q.all() will wait until all promises resolve to call .then(). This helps to ensure that all data is available when you start to use it.
Suggestion: Only assign properties and functions to $scope if they will be used by the view. I removed the functions that are not used by the view from the $scope object.
How does it work?
When the controller loads, we use $q.all() to invoke and wait for fetchAdminList() and fetchAppsList() to fetch data from an API. Once each API request resolves we unwrap the data in .then() callbacks and return it (read more on promise chaining to understand what happens when a value is returned from .then()). When both promises resolve, we store the data on $scope to make it available to the view. We also pre-compute which applications each user can use and store that data in $scope.userApps to make it available to the view.
I did not have access to the APIs you are fetching data from. I substituted $http calls with an immediately resolving promise using $q.resolve() and static data. When you are ready just replace $q.resolve(...) with the original $http(...) calls in the fetch functions.
Run the snippet to see it in action.
var app = angular.module('myApp', []);
(function () {
angular.element(document).ready(function () {
angular.bootstrap(document, ['myApp']);
});
})();
var USERS = [
{
Title: 'Software Engineer',
FirstName: 'C',
LastName: 'Foster',
EmployeeID: 1
},
{
Title: 'Software Engineer',
FirstName: 'J',
LastName: 'Hawkins',
EmployeeID: 2
},
{
Title: 'CEO',
FirstName: 'Somebody',
LastName: 'Else',
EmployeeID: 3
}
];
var APPS = [
{
Application: { Title: 'StackOverflow' },
Title: 'Software Engineer'
},
{
Application: { Title: 'Chrome' },
Title: 'Software Engineer'
},
{
Application: { Title: 'QuickBooks' },
Title: 'CEO'
}
]
app.controller('MainCtrl', function ($scope, $http, $q) {
$q.all({
users: fetchAdminList(),
apps: fetchAppsList()
})
.then(function(result) {
// Store results on $scope
$scope.users = result.users;
$scope.apps = result.apps;
// Pre-compute user apps
$scope.userApps = $scope.users.reduce(
function(userApps, user) {
userApps[user.EmployeeID] = getUserApps(user.Title);
return userApps;
},
[]
);
});
function fetchAdminList() {
return $q.resolve({ data: { d: { results: USERS } } })
.then(function (data) { return data.data.d.results; });
}
function fetchAppsList() {
return $q.resolve({ data: { d: { results: APPS } } })
.then(function (data) { return data.data.d.results; });
}
// Get a list of apps that apply to user title
function getUserApps(userTitle) {
return $scope.apps.filter(function(app) {
return app.Title === userTitle;
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.js"></script>
<div>
<div ng-controller="MainCtrl">
<div class="ProfileSheet" ng-repeat="user in users">
<h3 class="heading">User Profile</h3>
<table id="Profile">
<tr>
<th>User</th>
<td>{{user.Title}}</td>
</tr>
<tr>
<th>First Name</th>
<td>{{user.FirstName}}</td>
</tr>
<tr>
<th>Last Name</th>
<td>{{user.LastName}}</td>
</tr>
<tr>
<th>Job Title</th>
<td>{{user.JobTitle}}</td>
</tr>
<tr>
<th>Emp ID</th>
<td>{{user.EmployeeID}}</td>
</tr>
<tr>
<th>Officer Code</th>
<td>{{user.OfficerCode}}</td>
</tr>
<tr>
<th>Email</th>
<td>{{user.Email}}</td>
</tr>
<tr>
<th>Telephone</th>
<td>{{user.WorkPhone}}</td>
</tr>
<tr>
<th>Fax Number</th>
<td>{{user.WorkFax}}</td>
</tr>
<tr>
<th>Location Description</th>
<td>{{user.LocationDescription}}</td>
</tr>
<tr>
<th>Mailstop / Banking Center #</th>
<td>{{user.Mailstop}}</td>
</tr>
</table>
<br>
<h3 class="heading">User Applications</h3>
<div style="border:3px solid #707070; padding-right:12px;">
<h4 style="padding-left:5px;">User Applications</h4>
<table id="Apps">
<tr id="AppsHeading">
<th>Application</th>
<th>User ID</th>
<th>Initial Password</th>
<th>Options / Comment</th>
<th>Setup Status</th>
</tr>
<tr ng-repeat="app in userApps[user.EmployeeID]">
<td>{{app.Application.Title}}</td>
<td>{{app.Title}}</td>
<td>{{app.InitialPassword}}</td>
<td>{{app.OptionsComments}}</td>
<td style="border-right:3px solid #707070;">{{app.SetupStatus}}</td>
</tr>
</table>
</div>
</div>
</div>

Pass value to another controller in angularjs

I am new to AngularJS.
I have a div assigned controller to controller1. In this div, I am showing EmployeeList with three links for View, Edit,Delete for each employee.
I have another div assigned controller to controller2. By clicking the view link on any employee, I want to show full details in second div. Both divs are in same page.
How do I do that? Below is what I tried.
<div ng-controller="employeeController" style="border:solid black 3px;float:left;padding:5px">
<h3 style="color:#ff6a00">List Of Employees</h3>
<table>
<tr>
<th hidden>ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Full Name</th>
<th>Actions</th>
</tr>
<tr ng-repeat="employee in employees">
<td hidden><strong>{{ employee.ID }}</strong></td>
<td>{{ employee.FName }}</td>
<td>{{ employee.LName }}</td>
<td><strong>{{ employee.FName + ' ' + employee.LName }}</strong></td>
<td>
<a data-ng-click="GetEmployeeByID({{employee.ID}})" href="javascript:;">View</a>
</td>
</tr>
</table>
</div>
<div ng-controller="employeeByIDController" style="border:solid black 3px;float:right;padding:5px">
<h3 style="color:#ff6a00">Employee Details</h3>
<table>
<tr>
<th hidden>ID</th>
<th>Full Name</th>
<th>Qualification</th>
<th>Gender</th>
<th>Phone</th>
<th>Email</th>
<th>Address</th>
<th>City</th>
</tr>
<tr>
<td hidden><strong>{{ employeeByID.ID }}</strong></td>
<td>{{ employeeByID.FName + ' ' + employeeByID.LName }}</td>
<td>{{ employeeByID.Qualification }}</td>
<td>{{ employeeByID.Gender }}</td>
<td>{{ employeeByID.Phone }}</td>
<td>{{ employeeByID.Email }}</td>
<td>{{ employeeByID.Address }}</td>
<td>{{ employeeByID.City }}</td>
</tr>
</table>
</div>
The code in factory is as below.
mainApp.factory('EmployeeFactory', function ($http) {
return {
GetEmployeeList: function () {
return $http({
method: 'GET',
url: '/AngularEmployee/EmployeeList'
});
}
}
return {
GetEmployeeByID: function ($id) {
return $http({
method: 'GET',
url: '/AngularEmployee/EmployeeByID',
params: { empID : id }
});
}
}
});
I have added controller as follows.
mainApp.controller("employeeController", ['$scope', 'EmployeeFactory', function ($scope, EmployeeFactory) {
$scope.GetEmployeeList = function () {
EmployeeFactory.GetEmployeeList().success(function (data) {
$scope.employees = data;
}).error(function (data) {
$scope.error = "An Error has occured while Loading users! " + data.ExceptionMessage;
});
};$scope.GetEmployeeList();
}]);
Angular has a pubsub mechanism for this. It's well documented. E.g.:
https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/
if you want to share data between two controllers in angularJs , using a service or factory is a better option as service/factory in angularJs are injectable.But service/factory is a singleton object so be aware of the fact that same object of the service/factory will be shared by all the controllers.
Taking your example ,
you can create another service :
mainApp.service('sharedService',function(){
this.employee={};
this.getter=function(){
return this.employee;
};
this.setter=function(emp){
this.employee=emp;
};
});
Then you can share this service across your controllers to get or set employee.
mainApp.controller("employeeController", ['$scope', 'EmployeeFactory', 'sharedService', function($scope, EmployeeFactory, sharedService) {
$scope.GetEmployeeList = function() {
EmployeeFactory.GetEmployeeList().success(function(data) {
$scope.employees = data;
sharedService.setter($scope.employees);//set in shared service
}).error(function(data) {
$scope.error = "An Error has occured while Loading users! " + data.ExceptionMessage;
});
};
$scope.GetEmployeeList();
}]);
And then in employeeByIDControlle ,
mainApp.controller("employeeByIDController", ['$scope', 'EmployeeFactory', 'sharedService', function($scope, EmployeeFactory, sharedService) {
$scope.employees = sharedService.getter();//get from shared service
}]);

angular angular-table dynamic header name

I use angular and angular-table to display multiple tables on the same page.
I need to create dynamic table with dynamic header and dynamic content.
Plunkr her
This is a working example with non dynamic header but I don't find how to make dynamic
The controller :
angular.module('plunker', ['ui.bootstrap',"angular-table","angular-tabs"]);
function ListCtrl($scope, $dialog) {
$scope.cols= ['index','name','email'];
$scope.list = [
{ index: 1, name: "Kristin Hill", email: "kristin#hill.com" },
{ index: 2, name: "Valerie Francis", email: "valerie#francis.com" },
...
];
$scope.config = {
itemsPerPage: 5,
fillLastPage: true
};
}
HTML
<!-- this work -->
<table class="table table-striped" at-table at-paginated at-list="list" at-config="config">
<thead></thead>
<tbody>
<tr>
<td at-implicit at-sortable at-attribute="name"></td>
<td at-implicit at-sortable at-attribute="name"></td>
<td at-implicit at-sortable at-attribute="email"></td>
</tr>
</tbody>
</table>
<!-- this fail ... -->
<table class="table table-striped" at-table at-paginated at-list="list" at-config="config">
<thead></thead>
<tbody>
<tr>
<td ng-repeat='col in cols' at-implicit at-sortable at-attribute="{{col}}"></td>
</tr>
</tbody>
</table>
I am missing some think or it is not possible with this module ?
Did you know another module where you can have dynamic header and pagination ? ( i try also ngTable but have some bug issu with data not being displayed )
Through the below code, you can generate dynamic header
<table class="table table-hover table-striped">
<tbody>
<tr class="accordion-toggle tblHeader">
<th ng-repeat="(key, val) in columns">{{key}}</th>
</tr>
<tr ng-repeat="row in rows">
<td ng-if="!$last" ng-repeat="col in key(row)" ng-init="val=row[col]">
{{val}}
</td>
</tr>
</tbody>
</table>
Angular Script
var app = angular.module('myApp', []);
app.controller('myControl', function ($scope, $http) {
$http.get('http://jsonplaceholder.typicode.com/todos').success(function (data) {
$scope.columns = data[0];
$scope.rows = data;
}).error(function (data, status) {
});
$scope.key = function (obj) {
if (!obj) return [];
return Object.keys(obj);
}
});

How to call a function in controller from view

I want to call a function from my view which is
<table style="width:100%">
<thead>
<tr>
<td>Name</td>
<td>Class Name</td>
<td>UserName</td>
<td>Start Date</td>
<td>End Date</td>
</tr>
</thead>
<tr ng-repeat="student in students" ng-click="getStudent(student)">
<td>{{student.studentName}}</td>
<td>{{student.className}}</td>
<td>{{userName(student.userId)}}</td>
<td>{{student.startDate}}</td>
<td>{{student.endDate}}</td>
</tr>
</table>
I will get user id from the JSON object,
I want to get the name of the student by using user id with the following function in the controller
angular.module('studentApp.controllers').
controller('StudentController', ['$scope', 'InitialDataModel',
function ($scope, InitialDataModel) {
$scope.userName = function (id) {
var userObject = {};
userObject = _.findWhere(InitialDataModel.getUserObject, { "userId": id });
return userObject.userName;
}
}
])
But I am getting an error
Error: [$interpolate:interr]
Can't interpolate{{userName.getUserNameByUserId(student.userId)}}
TypeError: Object function (n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)} has no method 'findWhere'
How to remove this error?
Am I doing it in the right way?

Resources