In my application the user can do a search. When the search field is filled, a query is executed and a loading message appears until the complete execution of the request. This part is working perfectly.
I'm trying to pass the search string to another controller in order to come back on the main part with the previous results. This is working too but I don't know if I have used the best way...
MY PROBLEM: when I come back on the main part (search section), during the data reloading, the loading message is not displayed anymore, could you please help me to solve and update the code ?
Here my controller:
var app=angular.module('ContactsApp', ['ngRoute', 'ui.bootstrap', 'ngDialog']);
app.config(function($routeProvider, $httpProvider, ngDialogProvider){
$httpProvider.defaults.cache = false;
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
// disable IE ajax request caching
$httpProvider.defaults.headers.get['If-Modified-Since'] = '0';
ngDialogProvider.setDefaults({
className: 'ngdialog-theme-default',
plain: false,
showClose: true,
closeByDocument: true,
closeByEscape: true,
appendTo: false,
preCloseCallback: function () {
console.log('default pre-close callback');
}
});
//$httpProvider.requestInterceptors.push('httpRequestInterceptorCacheBuster');
// Add the interceptor to the $httpProvider to intercept http calls
$httpProvider.interceptors.push('HttpInterceptor');
$routeProvider.when('/all-contacts',
{
templateUrl: 'template/allContacts.html',
controller: 'ctrlContacts',
})
.when('/view-contacts/:contactId',
{
templateUrl: 'template/viewContact.html',
controller: 'ctrlViewContacts'
})
.otherwise({redirectTo:'/all-contacts'});
});
app.factory('httpInterceptor', function ($q, $rootScope, $log) {
var numLoadings = 0;
return {
request: function (config) {
numLoadings++;
// Show loader
$rootScope.$broadcast("loader_show");
return config || $q.when(config)
},
response: function (response) {
if ((--numLoadings) === 0) {
// Hide loader
$rootScope.$broadcast("loader_hide");
}
return response || $q.when(response);
},
responseError: function (response) {
if (!(--numLoadings)) {
// Hide loader
$rootScope.$broadcast("loader_hide");
}
return $q.reject(response);
}
};
})
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('httpInterceptor');
});
//LOADING ICON DURING LOADING DATA
app.directive("loader", function ($rootScope) {
return function ($scope, element, attrs) {
$scope.$on("loader_show", function () {
return element.show();
});
return $scope.$on("loader_hide", function () {
return element.hide();
});
};
}
)
//DIRECTIVE FOR PASSING A VARIABLE BETWEEN CONTROLER
app.factory('MyTextSearch', function() {
// private
var value = '';
// public
return {
getValue: function() {
return value;
},
setValue: function(val) {
value = val;
}
};
})
app.controller('ctrlContacts', function ($scope, MyTextSearch, ContactService){
$scope.searchText = "Search Name...";
console.log("INIT SEARCH:" + MyTextSearch.getValue() );
$scope.contacts=null;
$scope.searchButtonText = "Search";
$scope.test = false;
$scope.reSearch = function () {
// Do your searching here
// simulate search
$timeout(function () {
// search is complete
}, 2000);
}
function searchContact(searchText) {
// GET THE VALUE OF THE VARIABLE PASS TO THE CONTROLERS
MyTextSearch.setValue(searchText);
console.log("NEW SEARCH:" + searchText);
if (!searchText.length) {
$scope.stringToSearch="Search Name...";
}
if (searchText.length>2) {
$scope.loading = true;
$scope.test = true;
$scope.searchButtonText = "Loading...";
ContactService.fastSearch(searchText).success(function(contacts){
var length = contacts.length;
$scope.loading = false;
if (length == 0) {
$scope.searchButtonText = "No result";
}else {
$scope.searchButtonText = length + " results found";
}
// For the orderby date
for (var i=0; i<length; i++) {
if(contacts[i].REQUESTTRUEDATE!=""){
contacts[i].REQUESTTRUEDATE = new Date(contacts[i].REQUESTTRUEDATE.replace(/-/g,"/"));
}else{
contacts[i].REQUESTTRUEDATE=null;
}
}
$scope.contacts = contacts;
$scope.selIdx= -1;
$scope.selContact=function(contact,idx){
$scope.selectedContact=contact;
$scope.selIdx=idx;
window.location="#/view-contacts/" + idx;
}
$scope.isSelContact=function(contact){
return $scope.selectedContact===contact;
}
});
}else{
$scope.contacts=null;
}
}
if(MyTextSearch.getValue().length!=0){
// When come back on the result lists
var stringToSearch = MyTextSearch.getValue();
$scope.search = searchContact(stringToSearch);
//Usefull for reloading query if stringToSearch is updated
$scope.search = function(stringToSearch){
searchContact(stringToSearch);
}
}else{
// New search
$scope.search = function(searchText){
searchContact(searchText);
}
}
// recherche
$scope.searchText = null;
$scope.razRecherche = function() {
$scope.searchText = null;
console.log("RAZ");
MyTextSearch.setValue('');
$scope.contacts=null;
}
});
app.controller('ctrlViewContacts', function ($scope, $routeParams, MyTextSearch, ContactService, RequestService, ReportService){
// GET THE VALUE OF THE PREVIOUS SEARCH
$scope.searchText = MyTextSearch.getValue();
console.log("SEARCHTEXT: " + $scope.searchText );
$scope.contact = null;
ContactService.loadPersonById($routeParams.contactId).success(function(contact){
$scope.contact = contact;
});
});
Here my view:
<h3>View all contacts</h3>
<div class="spacer input-group">
<div class="input-group-addon">
<span class="glyphicon glyphicon-search"></span>
</div>
<input type="text" ng-model="searchText" class="form-control" placeholder="Search name..." ng-change="search(searchText)"/>
<div class="input-group-btn">
<button class="btn btn-default" ng-click="razRecherche()">
<span class="glyphicon glyphicon-remove"></span>
</button>
</div>
</div>
<div ng-show="(!searchText || (searchText.length)<3) && contacts==null && !searchButtonText" id="least3Characters">
<p class="spacer center"><strong>Please enter at least 3 characters</strong></p>
</div>
<div>
<p class="spacer center" ng-show="searchText && (searchText.length)>2" >
<img src="../img/loading.gif" class="ajax-loader" ng-show="loading==true"/>
<strong>{{ searchButtonText }}</strong>
</p>
</div>
<div class="table-responsive" id="allContacts">
<table ng-show="contacts.length" class="table table-striped table-hover spacer">
<thead>
<tr>
<th class="colPerson">
Person
<span class="hSpacer" ng-class="cssChevronsTri('PERSON')"></span>
</th>
<th class="colCompany">
Company
<span class="hSpacer" ng-class="cssChevronsTri('COMPANY')"></span>
</th>
<th class="colAction">Action</th>
</tr>
</thead>
<tbody ng-repeat="contact in contacts | filter:searchText | orderBy:champTri:triDescendant"
>
<tr class="clickable">
<td class="colPerson" ng-click="selContact(contact,contact.ID)" ng-class="{sel:selIdx==$index}">{{contact.PERSON}}</td>
<td class="colCompany" ng-click="selContact(contact,contact.ID)">{{contact.COMPANY}}</td>
<td class="colAction">
<span class="glyphicon glyphicon-pencil"></span>
<button class="inline btn btn-default" data-ng-click="confirmDelPerson(contact.ID, contact.NBREQUEST)">
<span class="glyphicon glyphicon-remove"></span>
</button>
</td>
</tr>
</tbody>
</table>
</div>
Many Thanks in advance for your help.
Related
this is my controller for WEB API.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using ShoppingCartAPINAngularJS.Models;
using System.Web.Http.Cors;
namespace ShoppingCartAPINAngularJS.Controllers
{
[Authorize]
public class CategoriesController : ApiController
{
private ShoppingCartEntities db = new ShoppingCartEntities();
// GET: api/Categories
public IQueryable<Category> GetCategories()
{
return db.Categories;
}
// GET: api/Categories/5
[ResponseType(typeof(Category))]
public IHttpActionResult GetCategory(int id)
{
Category category = db.Categories.Find(id);
if (category == null)
{
return NotFound();
}
return Ok(category);
}
// PUT: api/Categories/5
[ResponseType(typeof(void))]
public IHttpActionResult PutCategory(int id, Category category)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != category.CategoryID)
{
return BadRequest();
}
db.Entry(category).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!CategoryExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/Categories
[ResponseType(typeof(Category))]
public IHttpActionResult PostCategory(Category category)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Categories.Add(category);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = category.CategoryID }, category);
}
// DELETE: api/Categories/5
[ResponseType(typeof(Category))]
public IHttpActionResult DeleteCategory(int id)
{
Category category = db.Categories.Find(id);
if (category == null)
{
return NotFound();
}
db.Categories.Remove(category);
db.SaveChanges();
return Ok(category);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool CategoryExists(int id)
{
return db.Categories.Count(e => e.CategoryID == id) > 0;
}
}
}
and for calling this
// POST: api/Categories
[ResponseType(typeof(Category))]
public IHttpActionResult PostCategory(Category category)
i am using this angular js controller.js
(function () {
'use strict';
app.controller('categoryController', ['$http', '$location', 'authService', 'ngWEBAPISettings', categoryController]);
////categoryController.$inject = ['$location'];
function categoryController($http, $location, authService, ngWEBAPISettings) {
/* jshint validthis:true */
//Creating headers for sending the authentication token along with the system.
var authheaders = {};
authheaders.Authorization = 'Bearer ' + authService.getToken();
//ForDate
var d = new Date();
var vm = this;
vm.title = 'Category';
////debugger;
////Vadiable for Grid
vm.Category = [];
////Vadiable for Adding
vm.addCategory = {
categoryID: 0,
categoryName:"",
CreatedOn:d.getDate(),
UpdatedOn:d.getDate()
};
////Vadiable for Editing
vm.editCategory = {};
vm.getCategory = function () {
////debugger;
//For Grid
$http.get(ngWEBAPISettings.apiServiceBaseUri + "api/Categories", { headers: authheaders })
.then(function (respose) {
//success
////debugger;
angular.copy(respose.data, vm.Category);
////debugger;
//var i = 2;
////debugger;
}, function (response) {
//failure
////debugger;
}).finally(function () {
////debugger;
//finally
}
);
}
vm.add = function ()
{
////authheaders.Content-Type="application/x-www-form-urlencoded";
debugger;
$http.post(ngWEBAPISettings.apiServiceBaseUri + "api/Categories", vm.addCategory, { header: authheaders })
.then(function (repose) {
////success
debugger;
}, function (response) {
////failure
debugger;
}).finally(function () {
vm.addCategory = {};
});
}
vm.edit = function (id) {
///debugger;
alert(id);
$('#btnSubmit').val('Update');
}
vm.delete = function (id) {
////debugger;
alert(id);
}
activate();
function activate() { vm.getCategory(); }
}
})();
and this is the html file
(function () {
'use strict';
app.controller('categoryController', ['$http', '$location', 'authService', 'ngWEBAPISettings', categoryController]);
////categoryController.$inject = ['$location'];
function categoryController($http, $location, authService, ngWEBAPISettings) {
/* jshint validthis:true */
//Creating headers for sending the authentication token along with the system.
var authheaders = {};
authheaders.Authorization = 'Bearer ' + authService.getToken();
//ForDate
var d = new Date();
var vm = this;
vm.title = 'Category';
////debugger;
////Vadiable for Grid
vm.Category = [];
////Vadiable for Adding
vm.addCategory = {
categoryID: 0,
categoryName:"",
CreatedOn:d.getDate(),
UpdatedOn:d.getDate()
};
////Vadiable for Editing
vm.editCategory = {};
vm.getCategory = function () {
////debugger;
//For Grid
$http.get(ngWEBAPISettings.apiServiceBaseUri + "api/Categories", { headers: authheaders })
.then(function (respose) {
//success
////debugger;
angular.copy(respose.data, vm.Category);
////debugger;
//var i = 2;
////debugger;
}, function (response) {
//failure
////debugger;
}).finally(function () {
////debugger;
//finally
}
);
}
vm.add = function ()
{
////authheaders.Content-Type="application/x-www-form-urlencoded";
debugger;
$http.post(ngWEBAPISettings.apiServiceBaseUri + "api/Categories", vm.addCategory, { header: authheaders })
.then(function (repose) {
////success
debugger;
}, function (response) {
////failure
debugger;
}).finally(function () {
vm.addCategory = {};
});
}
vm.edit = function (id) {
///debugger;
alert(id);
$('#btnSubmit').val('Update');
}
vm.delete = function (id) {
////debugger;
alert(id);
}
activate();
function activate() { vm.getCategory(); }
}
})();
<h1>{{vm.title}}</h1>
<div id="addModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="gridSystemModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="gridSystemModalLabel">Add Category</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="control-label col-md-3">Category Name</label>
<input class="form-control col-md-9" type="text" name="txtcategoryname" id="txtcategoryname" maxlength="200" ng-model="vm.addCategory.categoryName" required />
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" id="btnSubmit" class="btn btn-primary" ng-disabled="!vm.addCategory.categoryName" ng-click="vm.add()">Add</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-md-offset-10">
<span class="fa fa-plus fa-200px"> </span> Add New Record
</div>
</div>
<table class="table table-responsive table-hover">
<thead>
<tr>
<th>Category Name</th>
<th>Created On</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="cat in vm.Category">
<td style="vertical-align:middle">{{cat.categoryName}}</td>
<td style="vertical-align:middle">{{cat.createdOn | date:'dd-MMM-yyyy' }}</td>
<td>
<input type="button" class="btn btn-sm btn-primary" ng-click="vm.edit(cat.categoryID)" value="Edit" />
<input type="button" class="btn btn-sm btn-primary" ng-click="vm.delete(cat.categoryID)" value="Delete" />
</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
function openAddModal() {
$('#addModal').modal('show');
$('#btnSubmit').val('Add');
}
</script>
from which i am getting to data to save it on server it has grid and one modal that open ups when add the data and i am planning to use the same modal for editing.
the problem that i am getting is shown in the picture below
cors is also enabled
cors is also enabled
cors is also enabled
after changing it from [Authorize] to [AllowAnonymous] it is saying bad request 400
I have pulled data from json file. Now its displayed over DOM.
On HTML Page, I have three option 1) Edit Data 2) Delete Particular Data & 3) Add New Data.
How to perform this using AngularJS Code? i.e. on editing name, it should update my JSON object. On Deleting row, it should delete that row in JSON data. and also If I click on Add New, then entered data will be added to JSON.
My Code is as below.
Importing data through json file and displaying on DOM
.controller('MainCtrl', function ($scope, $http) {
$http.get('data/home.json').
success(function(data, status, headers, config) {
$scope.details = data;
}).
error(function(data, status, headers, config) {
// log error
});
});
Output of this code is correct as below image.
JSON Object as below.
{
"status":"success",
"adformat":[
{
"adformat_id":1,
"name":"Format 1",
"size":"300x250"
},
{
"adformat_id":2,
"name":"Format 2",
"size":"320x250"
},
{
"adformat_id":3,
"name":"Format 3",
"size":"320x480"
}
]
}
I would do it like this:
MainCtrl.js
(function () {
'use strict';
angular
.module('app')
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope', 'MainFactory'];
function MainCtrl($scope, MainFactory) {
$scope.details = MainFactory.details;
function init() {
MainFactory.get();
}
init();
$scope.detailsModel = {
"adformat_id": 1,
"name": "Format 1",
"size": "300x250"
};
$scope.add = function () {
$scope.details.push($scope.detailsModel);
};
$scope.delete = function (index) {
$scope.details.splice(index, 1);
};
$scope.edited = -1;
$scope.editedModel = {
"adformat_id": 0,
"name": "",
"size": ""
};
$scope.edit = function (index) {
$scope.edited = index;
};
$scope.finishEdit = function (index) {
$scope.details[index] = $scope.editedModel;
$scope.edited = -1;
};
}
})();
MainFactory.js
(function () {
'use strict';
angular
.module('app')
.factory('MainFactory', MainFactory);
MainFactory.$inject = [];
function MainFactory() {
var self = this;
self.details = [];
self.get = $http.get('data/home.json')
.then(function (response) {
self.details = response.data;
}).catch(function (error) {
// log error
});
return self;
}
})();
index.html
<div ng-app="app">
<div ng-controller="MainCtrl">
<table>
<tbody>
<tr ng-repeat="details in detail">
<!-- show-->
<td ng-hide="edited === $index">{{detail.adformat_id}}</td>
<td ng-hide="edited === $index">{{detail.name}}</td>
<td ng-hide="edited === $index">{{detail.size}}</td>
<td ng-hide="edited === $index">
<button ng-click="edit($index)">Edit</button>
<button ng-click="delete($index)">Detele</button>
</td>
<!-- Edit-->
<td ng-show="edited === $index">{{detail.adformat_id}}</td>
<td ng-show="edited === $index"><input type="text" ng-model="editedModel.name"></td>
<td ng-show="edited === $index"><input type="number" ng-model="editedModel.size"></td>
<td ng-show="edited === $index">
<button ng-click="finishEdit($index, editedModel)">Save</button>
<button ng-click="delete($index)">Detele</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>
<button ng-click="add()">Add</button>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
It is just prototype, not tested, but it should help you to understand idea o two way binding in angular.
Here is my approach to this requirement. Let me know if any further improvement can be added. The entire code can be found at the below URL:
Angular Save, Update and Delete
The sample screenshots from the code can be found here...
controller:
'use strict';
function MainController($scope, SharedService, ngDialog) {
$scope.account_type_selected = "Savings";
$scope.sharedService = SharedService;
$scope.savingsMain = [];
$scope.checkingsMain = [];
$scope.addToCheckingsAccounts = {};
$scope.addToSavingsAccounts = {};
$scope.setAccountType = function (type) {
if (type === "allAccounts") {
$scope.showSavings = true;
$scope.showCheckings = true;
} else if (type === "savingsAccounts") {
$scope.showSavings = true;
$scope.showCheckings = false;
} else if (type === "checkingAccounts") {
$scope.showSavings = false;
$scope.showCheckings = true;
}
$scope.account_type_selected = type;
};
$scope.$watch('savingsMain', function ($scope) {
return $scope.savingsMain;
});
$scope.selectedAccountType = function (showAccount) {
console.log(showAccount);
if (showAccount === "Savings") {
$scope.sharedService.accountType = "Savings";
} else {
$scope.sharedService.accountType = "Checkings";
}
};
$scope.saveAccounts = function () {
if ($scope.sharedService.accountType === "Savings") {
$scope.addToSavingsAccounts = {
"account_type": $scope.sharedService.accountType,
"amount": $scope.sharedService.amount,
"date": $scope.sharedService.date,
"maturity": $scope.sharedService.maturity
};
$scope.showSavings = true;
$scope.savingsMain.push($scope.addToSavingsAccounts);
} else {
$scope.addToCheckingsAccounts = {
"account_type": $scope.sharedService.accountType,
"amount": $scope.sharedService.amount,
"bic": $scope.sharedService.BIC,
"iban": $scope.sharedService.IBAN
};
$scope.showCheckings = true;
$scope.checkingsMain.push($scope.addToCheckingsAccounts);
}
ngDialog.close();
};
$scope.deleteDataFromSharedService = function (accountType, item) {
if (accountType === "Savings") {
$scope.savingsMain = _.without($scope.savingsMain, _.findWhere($scope.savingsMain, { date: item }));
} else if (accountType === "Checkings") {
$scope.checkingsMain = _.without($scope.checkingsMain, _.findWhere($scope.checkingsMain, { bic: item }));
}
};
$scope.closeDialog = function () {
ngDialog.close();
};
$scope.accountTypeModel = [];
$scope.prop = {
"type": "select",
"name": "account_type",
"value": $scope.sharedService.accountType,
"accountTypeData": ["Savings", "Checkings"]
};
}
<form ng-controller="MainController">
<div class="page-header">
<h1>Angular-Save-Update-Delete</h1>
</div>
<div class="content-wrapper">
<div class="sidebar">
<table>
<tbody>
<tr>
<td>
<button ng-click="setAccountType('allAccounts')" ng-model="allAccounts" class="ng-pristine ng-untouched ng-valid ng-empty">All</button>
</td>
</tr>
<tr>
<td>
<button ng-click="setAccountType('savingsAccounts')" ng-model="savingsMain" class="ng-pristine ng-valid ng-not-empty ng-touched">Savings</button>
</td>
</tr>
<tr>
<td>
<button ng-click="setAccountType('checkingAccounts')" ng-model="checkingsMain" class="ng-pristine ng-untouched ng-valid ng-not-empty">Checkings</button>
</td>
</tr>
<tr>
<td>
<button class="create-account-btn-class"
type="button"
ng-dialog="app/views/create-account-template.html"
ng-dialog-data=""
ng-dialog-class="ngdialog-theme-default"
ng-dialog-scope="this"
plain=false
showClose=true
closeByDocument=true
closeByEscape=true
ng-dialog-show-close="false">New Account</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="right-content">
<div id="savingsTemplate" templateurl="app/views/savings.html" ng-show="showSavings" include-template=""></div>
<div id="checkingsTemplate" templateurl="app/views/checkings.html" ng-show="showCheckings" include-template=""></div>
</div>
</div>
</form>
In my angular js project factory is not providing values to the controller as needed. I always get empty result in view. When i logged in browser using console.log() all i can see in console is :
[object Object],[object Object],[object Object]. I am stuck at this. Tried many things but nothing worked.
This is my controller code:
var controllers = {};
controllers.ProductController = function ($scope, $route, $routeParams, $location, ProductFactory) {
$scope.products = [];
var init = function () {
$scope.products = ProductFactory.getProducts();
console.log('got products in controller');
console.log($scope.products)
};
var initProductEdit = function () {
var code = $routeParams.code;
if (code = undefined) {
$scope.currentProduct = {};
}
else
{
$scope.currentProduct = ProductFactory.loadProductByCode(code);
}
};
$scope.$on('$viewContentLoaded', function () {
var templateUrl = $route.current.templateUrl;
if (templateUrl == '/Partials/ProductEdit.html') {
initProductEdit();
}
else if (templateUrl == '/Partials/ProductList.html')
{
var code = $routeParams.code;
if(code!=undefined)
{
$scope.deleteProduct(code);
}
}
});
init();
$scope.saveProduct = function () {
ProductFactory.saveProduct($scope.currentProduct);
$location.search('code', null);
$location.path('/');
};
$scope.deleteProduct = function (code) {
ProductFactory.deleteProduct(code);
$location.search('code', null);
$location.path('/');
};
};
angSPA.controller(controllers);
This is my factory code:
angSPA.factory('ProductFactory', function () {
var products = [
{ code: 1, name: 'Game of Thrones', description: 'Series' }
{ code: 2, name: 'DmC', description: 'Game' },
{ code: 3, name: 'Matrix', description: 'Movie' },
{ code: 4, name: 'Linkin Park', description: 'Music Band' }];
var factory = {};
console.log('initializing factory');
factory.getProducts = function () {
console.log('factory now providing products');
return products;
};
factory.loadProductByCode = function (code) {
var product;
for (var i = 0; i < products.length; i++) {
if (products[i].code == code) {
product = products[i];
return product;
}
}
};
factory.saveProduct = function (product) {
products.push(product);
console.log('factory saved product');
};
factory.deleteProduct = function (code) {
var product = factory.loadProductByCode(code);
if (product != null) {
products.remove(product);
console.log('factory deleted product');
}
};
console.log('returning factory');
return factory;
});
This is my view:
<div class="container">
<h2 class="page-title">Product Listing</h2>
<div class="searchbar">
<ul class="entity-tabular-fields">
<li>
<label>Search: </label>
<span class="field-control">
<input type="text" data-ng-model="filter.productName" />
</span>
<label></label>
</li>
</ul>
</div>
<h2>Add New Product</h2>
<table class="items-listing">
<thead>
<tr>
<th>Code</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td data-ng-repeat="product in products|filter:filter.productName"></td>
<td>{{product.code}}</td>
<td>{{product.name}}</td>
<td>{{product.description}}</td>
<td>Delete</td>
</tr>
</tbody>
</table>
</div>
My routing function:
angSPA.config(function ($routeProvider) {
$routeProvider
.when(
'/',
{
controller: 'ProductController',
templateUrl: 'Partials/ProductList.html'
})
.when(
'/ProductEdit',
{
controller: 'ProductController',
templateUrl: 'Partials/ProductEdit.html'
})
.otherwise({
redirectTo: '/'
});
console.log('routing done');
});
Change your htmt given
var angSPA = angular.module('angSPA', []);
angSPA.controller("ProductController", function($scope, ProductFactory) {
$scope.products = [];
var init = function() {
$scope.products = ProductFactory.getProducts();
console.log('got products in controller');
console.log($scope.products + "")
};
init();
});
angSPA.factory('ProductFactory', function() {
var products = [
{code: 1, name: 'Game of Thrones', description: 'Series'},
{code: 2, name: 'DmC', description: 'Game'},
{code: 3, name: 'Matrix', description: 'Movie'},
{code: 4, name: 'Linkin Park', description: 'Music Band'}];
var factory = {};
console.log('initializing factory');
factory.getProducts = function() {
console.log('factory now providing products');
return products;
};
factory.loadProductByCode = function(code) {
var product;
for (var i = 0; i < products.length; i++) {
if (products[i].code == code) {
product = products[i];
return product;
}
}
};
factory.saveProduct = function(product) {
products.push(product);
console.log('factory saved product');
};
factory.deleteProduct = function(code) {
var product = factory.loadProductByCode(code);
if (product != null) {
products.remove(product);
console.log('factory deleted product');
}
};
console.log('returning factory');
return factory;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<body ng-app="angSPA" ng-controller="ProductController">
<div class="container">
<h2 class="page-title">Product Listing</h2>
<div class="searchbar">
<ul class="entity-tabular-fields">
<li>
<label>Search: </label>
<span class="field-control">
<input type="text" data-ng-model="filter.productName" />
</span>
<label></label>
</li>
</ul>
</div>
<h2>Add New Product</h2>
<table class="items-listing">
<thead>
<tr>
<th>Code</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="prod in products|filter:filter.productName">
<td ></td>
<td>{{prod.code}}</td>
<td>{{prod.name}}</td>
<td>{{prod.description}}</td>
<td>Delete</td>
</tr>
</tbody>
</table>
</div>
Your ng-repeat directive should be on the tr element and not the td.
<tr data-ng-repeat="product in products|filter:filter.productName">
Not the cause of your problem, but to log in a service or controller, you can use the $log service and stringify to serialize your objects.
$log.debug(JSON.stringify($scope.products));
Looking at your code, you do $scope.products = [] right at the beginning. This will make angular watch the empty array.
In your init function you assign the products array to $scope.products. But as angular is still watching the initial array it will not be aware of the change.
The solution is to delete the initial assignment $scope.products = [] and make sure to alter the original array but never set it to a new array.
BTW: you could do console.log(JSON.stringify($scope.products)) to get better log information.
I define a Service to share a variable between two controllers, but when i set the variable in a controller and then get this from another controller it does not get the correct value , this is the service:
App.service("ProductService", function () {
var productTotalCount = {};
return {
getproductTotalCount: function () {
return productTotalCount;
},
setproductTotalCount: function (value) {
productTotalCount = value;
}
}
});
and this is the controller which i set productTotalCount:
App.controller("ProductController", function ($scope, $http, $rootScope, ProductService) {
$scope.GetAllProducts = $http.get("GetAllProductsInformation").success(function (data) {
$rootScope.Products = data.Data;
ProductService.setproductTotalCount(data.TotalCount); // i set productTotalCount here and it's value became 19
});
$scope.editProduct = function (data) {
$scope.model = data;
$rootScope.$broadcast('modalFire', data)
}
});
and when i get the productTotalCount in this controller it return object instead of 19 :
App.controller('Pagination', function ($scope, ProductService) {
debugger;
$scope.totalItems = ProductService.getproductTotalCount(); // it should return 19 but return object!!
$scope.currentPage = 1;
$scope.itemPerPage = 8;
});
what is the problem?
EDIT: this is the html, it may help :
<div ng-controller="ProductController" ng-init="GetAllProducts()">
<div class="row" style="margin-top:90px" ng-show="!ShowGrid">
<article class="widget">
<header class="widget__header">
<div class="widget__title">
<i class="pe-7s-menu"></i><h3>ProductList</h3>
</div>
<div class="widget__config">
<i class="pe-7f-refresh"></i>
<i class="pe-7s-close"></i>
</div>
</header>
<div class="widget__content table-responsive">
<table class="table table-striped media-table">
<thead style="background-color:rgba(33, 25, 36,0.1)">
<tr>
<th style="width:40%">edit</th>
<th style="width:30%">Price</th>
<th style="width:30%">ProductName</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="product in Products">
#*<td>{{product.ProductDescription}}</td>*#
<td>
<input class="btn btn-default" style="padding: 14px;background: rgba(0, 0, 0, 0.2)" type="submit" value="Edit" ng-click="editProduct(product)" />
</td>
<td>{{product.Price}}</td>
<td>{{product.ProductName}}</td>
</tr>
</tbody>
</table>
</div>
</article>
</div>
</div>
<div ng-controller="Pagination">
<pagination total-items="totalItems" ng-change="pageChanged()" previous-text="Before" next-text="Next" first-text="First"
last-text="Last" ng-model="currentPage" items-per-page="itemPerPage" max-size="maxSize" class="pagination-sm" boundary-links="true"></pagination>
</div>
From the controller names, I bet the Pagination and ProductController controllers are both instantiated more or less at the same time, BEFORE invoking the .setproductTotalCount() method. If that is the case, then because you are treating the productTotalCount variable as a primitive type (instead of an object) after setting it, the changes do not get reflected between the controllers.
Try the following:
// Change the service to:
App.service("ProductService", function () {
var productTotalCount = {};
return {
getproductTotalCount: function () {
return productTotalCount;
},
setproductTotalCount: function (value) {
productTotalCount.value = value;
}
}
});
// In Pagination controller:
App.controller('Pagination', function ($scope, ProductService) {
debugger;
$scope.totalItems = ProductService.getproductTotalCount(); // this will still be an empty object initially, but when the value is updated in the service, the $scope.totalItems will also be updated
$scope.currentPage = 1;
$scope.itemPerPage = 8;
// this should confirm that changes are being propagated.
$scope.$watch('totalItems', function(newVal) {
console.log('totalItems updated. New Value:', newVal);
});
// NOTE: Keep in mind that the real productTotalCount will be stored as $scope.totalItems.value;
});
---- EDIT ----
Per your comment below, it proves that the solution above DOES work. To prove it, change:
$scope.$watch('totalItems', function(newVal) {
console.log('totalItems updated. New Value:', newVal);
});
to
$scope.$watch('totalItems', function(newVal) {
console.log('totalItems updated. New Value:', newVal);
console.log($scope.totalItems);
});
At that point, you should see that $scope.totalItems has been updated to:
{ value: 19 };
The issue may be how you're declaring your variable in your service. Because it's a local variable in the function rather than returned object, I believe it will be creating a new variable for each time you inject the service as a dependency. Try making the variable a member of the returned object. E.g.
App.service("ProductService", function () {
return {
productTotalCount: 0,
getproductTotalCount: function () {
return this.productTotalCount;
},
setproductTotalCount: function (value) {
this.productTotalCount = value;
}
}
});
I have a set of DIV's that contain A's and use AngularUI to load Angular templates within a ui-view DIV. I'm implementing a set of tabs that switch between the view templates based on which one a user clicks. I have several of these within the application and all work as designed. However, on one of my pages I keep getting a "TypeError: Cannot read property 'name' of undefined" that blows up in the angular-ui-router isMatch() call in the $StateRefActiveDirective($state, $stateParams, $interpolate) function on the line 'return $state.includes(state.name) && matchesParams();' because state is not defined. I've stepped through the calls to this code and it processes all of the ui-srefs in my markup successfully. Then after those are processed it gags.
The only real difference between other pages with these tabs on them is that I have the other pages with no other markup on them except the tabs and their ui-views. On this one I have 2 bootstrap columns, a col-md-5 and col-md-7. The col-md-5 contains a table of objects. When the user clicks on one of the rows the col-md-7 is shown, the $state is changed to one of its tabs and the data for the object is loaded for the tab by its controller.
On the other pages the tabs are always displayed and clicking them takes you to different ui-views the same as the my problem child. One real difference between them is a directive I wrote to 'disable' the links based on a Boolean. The uiSrefIf directive is at the bottom of the JavaScript listing. The idea is that when the File tab is shown the other tabs are visible but disabled.
Here is the JavaScript and markup:
angular.module('meritApp.screens.importUsers', [
'ui.router', 'ngSanitize', 'ui.select', 'ui.bootstrap', 'meritApp.global.services.profile',
'meritApp.global.services.common', 'angularFileUpload', 'meritApp.global.services.managedFiles'
])
.config(function($stateProvider) {
$stateProvider
.state('importUsers', {
url: "/admin/importUsers",
templateUrl: "app/screens/admin/importUsers/importUsers.html?v=" + APP_VERSION
});
$stateProvider
.state('importUsers.file', {
url: "/file",
templateUrl: "app/screens/admin/importUsers/file.html?v=" + APP_VERSION
});
$stateProvider
.state('importUsers.inserted', {
url: "/inserted",
templateUrl: "app/screens/admin/importUsers/inserted.html?v=" + APP_VERSION
});
$stateProvider
.state('importUsers.insertError', {
url: "/insertError",
templateUrl: "app/screens/admin/importUsers/insertError.html?v=" + APP_VERSION
});
$stateProvider
.state('importUsers.skipped', {
url: "/skipped",
templateUrl: "app/screens/admin/importUsers/skipped.html?v=" + APP_VERSION
});
$stateProvider
.state('importUsers.updated', {
url: "/updated",
templateUrl: "app/screens/admin/importUsers/updated.html?v=" + APP_VERSION
});
})
.controller('importUsersController', [
'$scope', '$state', '$log', '$rootScope', '$filter', 'appConfig', '$http', 'roleSvc',
function($scope, $state, $log, $rootScope, $filter, appConfig, $http, roleSvc) {
$rootScope.$broadcast("SET_BREADCRUMB", []);
$scope.itemsPerPage = 10;
$scope.currentPage = 1;
$rootScope.importing = false;
$rootScope.roleChanged = function(user, role) {
// todo - set the user's role
};
$scope.newImport = function() {
$rootScope.importing = true;
$rootScope.savedLocation = $rootScope.selectedLocation;
$rootScope.selectedLocation = null;
};
$rootScope.defaultRole = {
name: "Associate"
};
roleSvc.listAllActive(0, 40).then(
function(response) {
$rootScope.roles = $filter('orderBy')(response.data.results, "name");
angular.forEach($rootScope.roles, function(role) {
if (role.name == "Associate") {
$rootScope.defaultRole = role;
}
});
},
function(err) {
console.log("roleSvc.listAllActive Error: " + err.status + " " + err.statusText);
});
var init = function() {
$scope.loading = true;
$scope.locations = [];
var skip = ($scope.currentPage - 1) * $scope.itemsPerPage;
var userImportQueryPath = "queries/Merit.Components.UserImport.Queries/UserImportQueries";
$http.get(appConfig.urlRoot + userImportQueryPath + "/GetImportSummaries/results").then(
function(response) {
$scope.totalItems = response.data.results.length;
angular.forEach(response.data.results, function(location) {
if (skip-- <= 0 && $scope.locations.length < $scope.itemsPerPage) {
$scope.locations.push(location);
}
});
$scope.loading = false;
}, function(err) {
alert("GetImportList Error: " + err.status + " - " + err.statusText);
});
$http.get(appConfig.urlRoot + userImportQueryPath + "/GetAuditRecords/results").then(
function(response) {
$rootScope.importData = [];
angular.forEach(response.data.results, function(record) {
record["isInvited"] = false;
record["selectedRole"] = $rootScope.defaultRole;
record.errorText = JSON.parse(record.errorText);
$rootScope.importData.push(record);
});
$scope.users = _.sortBy($rootScope.importData, 'employeeId');
}, function(err) {
alert("GetImportList Error: " + err.status + " - " + err.statusText);
});
};
init();
$scope.refresh = function() {
init();
};
$scope.viewImports = function(location) {
$rootScope.selectedLocation = location;
$state.go('importUsers.inserted', {}, {
reload: true
});
};
$rootScope.closeView = function() {
$rootScope.importing = false;
if ($rootScope.savedLocation) {
$rootScope.selectedLocation = $rootScope.savedLocation;
$rootScope.savedLocation = null;
} else {
$rootScope.selectedLocation = null;
}
};
$scope.inviteUsers = function() {
angular.forEach($scope.users, function(userArray) {
if (userArray) {
angular.forEach(userArray, function(user) {
if (user.isInvited) {
// todo - send email to invited user
console.log("Sending email to " + user.name);
user.isInvited = false;
}
});
}
});
};
}
])
.controller('iuInsertedController', [
'$scope', '$state', '$log', '$rootScope',
function($scope, $state, $log, $rootScope) {
$rootScope.$broadcast("SET_BREADCRUMB", []);
$scope.itemsPerPage = 10;
$scope.selectedTab = "Inserted";
$scope.currentPage = 1;
$scope.inviteCount = 0;
var init = function() {
$scope.users = [];
$scope.totalItems = 0;
if (!$rootScope.selectedLocation) return;
var skip = ($scope.currentPage - 1) * $scope.itemsPerPage;
angular.forEach($rootScope.importData, function(user) {
if (user.isInserted && !user.hasErrors && user.locationCode == $rootScope.selectedLocation.code && user.timestampUtc == $rootScope.selectedLocation.timeStampUtc) {
if (skip-- <= 0 && $scope.users.length < $scope.itemsPerPage)
$scope.users.push(user);
$scope.totalItems++;
}
});
};
init();
$scope.refresh = function() {
init();
};
$scope.invite = function(user) {
$scope.inviteCount = (user.isInvited ? $scope.inviteCount + 1 : $scope.inviteCount - 1);
};
$scope.inviteUsers = function() {
alert("todo - send email to invited users");
angular.forEach($scope.users, function(user) {
if (user.isInvited) {
// todo - send email to invited user
console.log("Sending email to " + user.name);
user.isInvited = false;
}
});
};
}
])
.controller('iuInsertErrorController', [
'$scope', '$state', '$log', '$rootScope',
function($scope, $state, $log, $rootScope) {
$rootScope.$broadcast("SET_BREADCRUMB", []);
$scope.itemsPerPage = 10;
$scope.currentPage = 1;
$scope.selectedTab = "Inserted with Errors";
var importData = $rootScope.importData;
var init = function() {
$scope.users = [];
$scope.totalItems = 0;
if (!$rootScope.selectedLocation) return;
var skip = ($scope.currentPage - 1) * $scope.itemsPerPage;
angular.forEach(importData, function(user) {
if (user.isInserted && user.hasErrors && user.locationCode == $rootScope.selectedLocation.code && user.timestampUtc == $rootScope.selectedLocation.timeStampUtc) {
if (skip-- <= 0 && $scope.users.length < $scope.itemsPerPage)
$scope.users.push(user);
$scope.totalItems++;
}
});
};
init();
$scope.refresh = function() {
init();
};
$scope.inviteUsers = function() {
angular.forEach($scope.users, function(userArray) {
if (userArray) {
angular.forEach(userArray, function(user) {
if (user.isInvited) {
// todo - send email to invited user
console.log("Sending email to " + user.name);
user.isInvited = false;
}
});
}
});
};
}
])
.controller('iuUpdatedController', [
'$scope', '$state', '$log', '$rootScope',
function($scope, $state, $log, $rootScope) {
$rootScope.$broadcast("SET_BREADCRUMB", []);
$scope.itemsPerPage = 10;
$scope.currentPage = 1;
$scope.selectedTab = "Updated";
var init = function() {
$scope.users = [];
$scope.totalItems = 0;
if (!$rootScope.selectedLocation) return;
var skip = ($scope.currentPage - 1) * $scope.itemsPerPage;
angular.forEach($rootScope.importData, function(user) {
if (user.isUpdated && user.locationCode == $rootScope.selectedLocation.code && user.timestampUtc == $rootScope.selectedLocation.timeStampUtc) {
if (skip-- <= 0 && $scope.users.length < $scope.itemsPerPage)
$scope.users.push(user);
$scope.totalItems++;
}
});
};
init();
$scope.refresh = function() {
init();
};
$scope.inviteUsers = function() {
angular.forEach($scope.users, function(userArray) {
if (userArray) {
angular.forEach(userArray, function(user) {
if (user.isInvited) {
// todo - send email to invited user
console.log("Sending email to " + user.name);
user.isInvited = false;
}
});
}
});
};
}
])
.controller('iuSkippedController', [
'$scope', '$state', '$log', '$rootScope',
function($scope, $state, $log, $rootScope) {
$rootScope.$broadcast("SET_BREADCRUMB", []);
$scope.itemsPerPage = 10;
$scope.currentPage = 1;
$scope.selectedTab = "Skipped";
var init = function() {
$scope.users = [];
$scope.totalItems = 0;
if (!$rootScope.selectedLocation) return;
var skip = ($scope.currentPage - 1) * $scope.itemsPerPage;
angular.forEach($rootScope.importData, function(user) {
if (user.wasSkipped && user.locationCode == $rootScope.selectedLocation.code && user.timestampUtc == $rootScope.selectedLocation.timeStampUtc) {
if (skip-- <= 0 && $scope.users.length < $scope.itemsPerPage)
$scope.users.push(user);
$scope.totalItems++;
}
});
};
init();
$scope.refresh = function() {
init();
};
$scope.inviteUsers = function() {
angular.forEach($scope.users, function(userArray) {
if (userArray) {
angular.forEach(userArray, function(user) {
if (user.isInvited) {
// todo - send email to invited user
console.log("Sending email to " + user.name);
user.isInvited = false;
}
});
}
});
};
}
])
.controller('iuFileController', [
'$scope', '$state', '$log', '$rootScope', 'managedFileSvc', 'commandSvc', 'appConfig', '$http', 'modalMsgSvc',
function($scope, $state, $log, $rootScope, managedFileSvc, commandSvc, appConfig, $http, modalMsgSvc) {
$rootScope.$broadcast("SET_BREADCRUMB", []);
$scope.locations = mockExtraLocations;
$scope.importLocation = undefined;
$scope.importFile = undefined;
$scope.buttonText = "Browse...";
var locationsQueryPath = "queries/Merit.Components.Locations.Queries/LocationQueries";
$http.get(appConfig.urlRoot + locationsQueryPath + "/FindAllActive/results?skip=" + 0 + "&pageSize=" + 20).then(
function(response) {
$scope.locations = response.data.results;
}, function(err) {
console.log("LocationQueries.FindAllActive Error: " + err.status + " - " + err.statusText);
});
$scope.doImport = function() {
managedFileSvc.uploadFile($scope.importFile, function(evt) {
console.log(evt);
$scope.uploadProgress = evt;
}, function(response) {
console.log('upload response :: File ID: ', response[0].QueryReferences[0].QueryParameter);
var command = {
ImportFileId: response[0].QueryReferences[0].QueryParameter,
LocationCode: $scope.importLocation.code,
LocationName: $scope.importLocation.name
};
modalMsgSvc.showLoading("Importing...");
commandSvc.publish('Merit.Components.User.Commands', 'ImportHumanicUsers', command)
.then(function(record) {
modalMsgSvc.hideLoading();
console.log("ImportHumanicUsers Published: " + record.status);
$scope.importFile = undefined;
$rootScope.closeView();
$state.go("importUsers", {}, {
reload: true
});
}, function(err) {
modalMsgSvc.hideLoading();
if (err.errors)
console.log("ImportHumanicUsers ERROR: " + err.errors[0]);
else if (err.errorHeadline)
console.log("ImportHumanicUsers ERROR: " + err.errorHeadline);
else
console.log("ImportHumanicUsers ERROR: unknown");
// TODO?
});
});
};
$scope.fileSelected = function(files) {
// even though ng-multiple is false, we still get an array
if (files != null) {
$scope.importFile = files[0];
}
};
$scope.cancelImport = function() {
$scope.importFile = undefined;
$rootScope.closeView();
if ($rootScope.selectedLocation)
$state.go("importUsers.inserted");
};
}
])
.directive('uiSrefIf', function($compile) {
return {
scope: {
val: '#uiSrefVal',
if : '=uiSrefIf'
},
link: function($scope, $element, $attrs) {
$element.removeAttr('ui-sref-if');
$compile($element)($scope);
$scope.$watch('if', function(bool) {
if (bool) {
$element.attr('ui-sref', $scope.val);
} else {
$element.removeAttr('ui-sref');
$element.removeAttr('href');
}
$compile($element)($scope);
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="importUsersController">
<div class="row">
<div class="col-md-5">
<div class="table importLocationsCol">
<div class="row headerRow titleBar">
<div class="col-md-9"><i class="icon-users"></i>Import Users</div>
<div class="col-md-3 importNewBtnDiv">
<div class="btn btn-cancel importNewButton" ng-click="newImport()" ui-sref-opts="{reload: true}">
<a ui-sref="importUsers.file" style="text-decoration: none !important; color: #585858;">New</a>
</div>
</div>
</div>
<div class="row">
<h4>Past Imports</h4>
</div>
<div class="row">
<table class="table table-striped deptTable importTable">
<thead>
<tr>
<th class="importNameCol">Location</th>
<th class="importCountsCol">Update / New / Skip</th>
<th class="importDateCol">Imported</th>
</tr>
</thead>
<tbody>
<tr ng-show="loading && locations && locations.length == 0">
<td colspan="3">
<br />
<br />
<img class="spinner" src="content/images/ajax-loader.gif" alt="Loading..." />
</td>
</tr>
<tr ng-hide="true">
<td>
<!-- trick angular into making the next row white -->
</td>
</tr>
<tr ng-repeat=" location in locations" ng-class="{selected: location.code == selectedLocation.code}" ng-show="locations && locations.length > 0" ng-click="viewImports(location)">
<td class="importNameCol">{{location.name}} - {{location.city}}, {{location.state}}</td>
<td class="importCountsCol">{{location.updated}} / {{location.inserted}} / {{location.skipped}}</td>
<td class="importDateCol">{{location.timeStampUtc | date:'MM/dd/yyyy'}}</td>
</tr>
<tr ng-hide="loading || (locations && locations.length > 0)">
<td colspan="3" class="text-center">No Imports Found.</td>
</tr>
</tbody>
</table>
</div>
<div class="row">
<div class="col-md-12 paginationRow">
<pagination total-items="totalItems" items-per-page="itemsPerPage" ng-model="currentPage" max-size="5" ng-show="totalItems > itemsPerPage || true" direction-links="false" boundary-links="false" rotate="false" ng-change="refresh()" class="pagination-sm pull-right"></pagination>
</div>
</div>
</div>
</div>
<div class="col-md-7">
<div class="table importViewCol" ng-show="selectedLocation != null || importing">
<div class="row headerRow titleBar">
<div class="col-md-9">
<i class="icon-users"></i><span ng-show="importing">New</span><span ng-hide="importing">View</span> Import
</div>
<div class="col-md-3 text-right" ng-click="closeView()"><i class="icon-close"></i>
</div>
</div>
<div class="editWorkOrder" style="padding-bottom: 0; border: 0;">
<div class="tabBox">
<div class="tabStrip">
<div class="tab" ng-show="importing" ui-sref-opts="{reload: true}" ui-sref-active="thisTab">
<a ui-sref="importUsers.file">File</a>
</div>
<div class="tab" ui-sref-opts="{reload: true}" ui-sref-active="thisTab" ng-disabled="importing">
<a ui-sref-if="!importing" ui-sref-val="importUsers.inserted">Inserted</a>
</div>
<div class="tab" ui-sref-opts="{reload: true}" ui-sref-active="thisTab" ng-disabled="importing">
<a ui-sref-if="!importing" ui-sref="importUsers.insertError">Inserted with Errors</a>
</div>
<div class="tab" ui-sref-opts="{reload: true}" ui-sref-active="thisTab" ng-disabled="importing">
<a ui-sref-if="!importing" ui-sref="importUsers.updated">Updated</a>
</div>
<div class="tab" ui-sref-opts="{reload: true}" ui-sref-active="thisTab" ng-disabled="importing">
<a ui-sref-if="!importing" ui-sref="importUsers.skipped">Skipped</a>
</div>
</div>
</div>
</div>
<div class="importUsersDisplay" ui-view></div>
</div>
</div>
</div>
</div>
Because we use so many service calls I haven't tried to get this working in Plunker. It's not a show stopper since the page behaves as expected. It is an annoyance that I'd like to understand and eliminate. Also, my QA folks can then stop complaining to me about it :)
Thanks, Mike