I am trying to create a basic CRUD application using JayData, AngularJS and OData Web Api. I have got so far as creating a List view and an Edit view and when clicking on the Edit option for an item in the List view it successfully redirects to the Edit view and it is populated as expected. However, when I go back to the List view and select subsequent Edit options, the Edit view does not get populated. Here is my relevant Angular code :
EDIT : Here is my complete code, as requested :
app.js :
var app = angular.module("app", ["localization", "ngResource", "ngRoute", "jaydata"]).
config(function ($routeProvider, $locationProvider) {
$routeProvider.
when('/Admin/Fixtures/List', { controller: FixtureListController, templateUrl: '/Content/Templates/Fixtures.html' }).
when('/Admin/Fixtures/Add', { controller: FixtureAddController, templateUrl: '/Content/Templates/FixtureAddEdit.html' }).
when('/Admin/Fixtures/Edit/:fixtureId', { controller: FixtureEditController, templateUrl: '/Content/Templates/FixtureAddEdit.html' }).
otherwise({ controller: TeamListController, redirectTo: 'Admin/Teams/List', templateUrl: '/Content/Templates/Teams.html' });
$locationProvider.html5Mode(true); //will use html5 mode rather than hashbang where available
});
var FixtureListController = function ($scope, $data) {
$scope.fixtures = [];
$scope.context = [];
$scope.selectedFixture = null;
$data.initService('http://lovelyjubbly.cloudapp.net/odata')
.then(function (context) {
$scope.context = context;
$scope.fixtures = context.Fixtures.include('Stage').include('HomeTeam').
include('AwayTeam').include('City').toLiveArray();
});
$scope.delete = function () {
//get id, can use this to get item from ng-repeat
var emp = new lovelyjubblyWebApi.Models.Fixture({ FixtureId: this.fixture.FixtureId });
$scope.context.Fixtures.remove(emp);
$scope.context.saveChanges();
};
};
//crud controllers
var FixtureAddController = function ($scope, $data) {
$scope.fixtures = [];
$data.initService('http://lovelyjubbly.cloudapp.net/odata')
.then(function (context) {
$scope.context = context;
$scope.fixtures = context.Fixtures.toLiveArray();
$scope.teams = context.Teams.toLiveArray();
$scope.cities = context.Cities.toLiveArray();
$scope.stages = context.Stages.toLiveArray();
});
$scope.save = function () {
//prevents a separate post
$scope.fixture.entityState = $data.EntityState.Modified;
$scope.context.Fixtures.add($scope.fixture, true);
$scope.context.saveChanges();
//reset state
$scope.context.stateManager.reset();
};
};
var FixtureEditController = function ($scope, $data, $routeParams) {
$scope.context = [];
$scope.fixtures = [];
$scope.teams = [];
$scope.cities = [];
$scope.stages = [];
$scope.selectedFixture = null;
$scope.fixture = null;
$data.initService('http://lovelyjubbly.cloudapp.net/odata')
.then(function (context) {
$scope.context = context;
$scope.fixtures = context.Fixtures.include('Stage').include('HomeTeam').
include('AwayTeam').include('City').toLiveArray();
$scope.teams = context.Teams.toLiveArray();
$scope.cities = context.Cities.toLiveArray();
$scope.stages = context.Stages.toLiveArray();
var emp = new lovelyjubblyWebApi.Models.Fixture({ FixtureId: $routeParams.fixtureId });
$scope.context.Fixtures.filter('FixtureId', '==', $routeParams.fixtureId)
.forEach(function (item) {
emp.StageId = item.StageId;
emp.CityId = item.CityId;
emp.FixtureDate = item.FixtureDate;
emp.HomeTeamId = item.HomeTeamId;
emp.HomeTeamScore = item.HomeTeamScore;
emp.AwayTeamId = item.AwayTeamId;
emp.AwayTeamScore = item.AwayTeamScore;
}).then(function (e)
{
$scope.fixture = emp;
});
$scope.save = function () {
if ($scope.form.$valid) { //check for valid form
var todo = $scope.context.Fixtures.attachOrGet({ FixtureId: $routeParams.fixtureId });
todo.StageId = $scope.fixture.StageId;
todo.CityId = $scope.fixture.CityId;
//emp2.FixtureDate = $scope.fixture.FixtureDate;
todo.FixtureDate = "10/10/2014 00:00";
todo.HomeTeamId = $scope.fixture.HomeTeamId;
todo.HomeTeamScore = $scope.fixture.HomeTeamScore;
todo.AwayTeamId = $scope.fixture.AwayTeamId;
todo.AwayTeamScore = $scope.fixture.AwayTeamScore;
$scope.context.saveChanges();
} else {
alert("invalid form");
}
};
});
};
List view:
<table class="table table-striped table-condensed table-hover">
<thead>
<th>
Fixture Id
</th>
<th>
Fixture Date
</th>
<th>
Stage
</th>
<th>
City
</th>
<th>
Home Team
</th>
<th>
Score
</th>
<th>
Away Team
</th>
<th>
Score
</th>
</thead>
<tbody>
<tr ng-repeat="fixture in fixtures | orderBy:'FixtureId'" id="fixture_{{fixture.FixtureId}}">
<td>{{fixture.FixtureId}}</td>
<td>{{fixture.FixtureDate}}</td>
<td>{{fixture.Stage.StageName}}</td>
<td>{{fixture.City.CityName}}</td>
<td>{{fixture.HomeTeam.TeamName}}</td>
<td>{{fixture.HomeTeamScore}}</td>
<td>{{fixture.AwayTeam.TeamName}}</td>
<td>{{fixture.AwayTeamScore}}</td>
<td>
<i class="glyphicon glyphicon-edit"></i>
<a ng-click="delete()"><i class="glyphicon glyphicon-remove"></i></a>
</td>
</tr>
</tbody>
</table>
Add/Edit view :
<form name="form" class="col-xs-2" id="form" class="form-horizontal">
<div class="control-group" ng-class="{error: form.StageName.$invalid}">
<label class="control-label" for="StageName">Stage Team</label>
<div class="controls">
<select class="form-control" ng-model="fixture.StageId" ng-options="stage.StageId as stage.StageName for stage in stages" required>
<option style="display:none" value="">Select</option>
</select>
<span ng-show="form.StageName.$dirty && form.StageName.$error.required">Stage required</span>
</div>
</div>
<div class="control-group" ng-class="{error: form.CityName.$invalid}">
<label class="control-label" for="CityName">City</label>
<div class="controls">
<select class="form-control" ng-model="fixture.CityId" ng-options="city.CityId as city.CityName for city in cities" required>
<option style="display:none" value="">Select</option>
</select>
<span ng-show="form.CityName.$dirty && form.CityName.$error.required">City required</span>
</div>
</div>
<div class="control-group" ng-class="{error: form.FixtureDate.$invalid}">
<label class="control-label" for="BirthDate">Fixture Date</label>
<div class="controls">
<input type='text' class="form-control" ng-model="fixture.FixtureDate" name='FixtureDate' title="FixtureDate" />
</div>
</div>
<div class="control-group" ng-class="{error: form.HomeTeamName.$invalid}">
<label class="control-label" for="HomeTeamName">Home Team</label>
<div class="controls">
<select class="form-control" ng-model="fixture.HomeTeamId" ng-options="team.TeamId as team.TeamName for team in teams" required>
<option style="display:none" value="">Select</option>
</select>
<span ng-show="form.HomeTeamName.$dirty && form.HomeTeamName.$error.required">Home Team required</span>
</div>
</div>
<div class="control-group" ng-class="{error: form.HomeTeamScore.$invalid}">
<label class="control-label" for="HomeTeamScore">Home Team Score</label>
<div class="controls">
<input type="text" class="form-control" placeholder="Score" ng-model="fixture.HomeTeamScore" id="HomeTeamScore" name="HomeTeamScore" />
</div>
</div>
<div class="control-group" ng-class="{error: form.AwayTeamName.$invalid}">
<label class="control-label" for="AwayTeamName">Away Team</label>
<div class="controls">
<select class="form-control" ng-model="fixture.AwayTeamId" ng-options="team.TeamId as team.TeamName for team in teams" required>
<option style="display:none" value="">Select</option>
</select>
<span ng-show="form.AwayTeamName.$dirty && form.AwayTeamName.$error.required">Away Team required</span>
</div>
</div>
<div class="control-group" ng-class="{error: form.AwayTeamScore.$invalid}">
<label class="control-label" for="AwayTeamScore">Away Team Score</label>
<div class="controls">
<input type="text" class="form-control" placeholder="Score" ng-model="fixture.AwayTeamScore" id="AwayTeamScore" name="AwayTeamScore" />
</div>
</div>
<br />
<div class="form-actions">
<button ng-show="form.$valid" ng-click="save()" class="btn btn-primary">{{action}}</button>
Cancel
</div>
</form>
This is a little tricky as we do not see the code for making a selection, routes, or how the controllers are invoked.
However, I believe that only one instance of the FixtureEditController is being created. You can test this by adding a breakpoint or console log to FixtureEditController.
Therefore, the call to:
$data.initService('http://lovelyjubbly.cloudapp.net/odata')
and
var emp = new lovelyjubblyWebApi.Models.Fixture({ FixtureId: $routeParams.fixtureId });
are only made once.
In the edit controller. you will want to detect when the route param changes so you can take action.
$scope.routeParams = $routeParams;
$data.initService('http://lovelyjubbly.cloudapp.net/odata')
.then(function (context) {
$scope.$watch('$routeParams',function(routeParams){
// this should run on any change in routeParams (regardless of the current state)
},true);
I am not certain that watching routeParams is the best approach, if the edit controller is inheriting from the list controller then you could watch "selectedFixture".
Related
I am creating a restaurant menu app that a waiter can use to input orders.
I have a Js array called itemOrderList that I am storing item names in. I want to be able to send that list of item names as Json array with customer name form input field and item price to back end to be stored in my DB. I am having issues going about doing this. What should I do? Google dev tools says "ReferenceError: itemOrderList is not defined" where I am trying to stringify the Js array.
AngularJs code
.controller('orderAddCtrl', ['$scope', '$location', 'dataService', function ($scope, $location, dataService) {
$scope.itemOrderList = [];
$scope.totalItemPrices = 0;
$scope.addOrderToList = function (item) {
console.log(item.itemName);
$scope.addPricesToTotalItemPrices(item.itemPrice);
$scope.itemOrderList.push(item.itemName);
};
$scope.addPricesToTotalItemPrices = function (price) {
console.log(price);
$scope.totalItemPrices += price ;
};
$scope.removeFromOrderToList = function (index) {
console.log(index);
$scope.itemOrderList.splice(index, 1);
};
$scope.createOrder = function (order) {
var myJson = JSON.stringify(itemOrderList);
order.orderPrice = totalItemPrices;
order.orderItems = myJson;
dataService.addOrder(order).then(function () {
$location.path('/');
});
};
Html
<form class="form-horizontal" ng-init="getItems()">
<div class="row">
<div class="col-6">
<div class="form-group">
<div>
<input ng-click="createOrder(order)" class="btn btn-success" value="Create" />
Back
</div>
</div>
</div>
<div class="col-6">
<div class="form-group">
<label class="control-label">Customer Name</label>
<div class="col-lg-10">
<input type="text" class="form-control" ng-model="order.customerName" />
</div>
</div>
</div>
</div>
<div>
<h1>Total Price: ${{totalItemPrices}}</h1>
</div>
<div class="">
<h2>Food Items</h2>
<div class="row">
<button class="btn btn-success col-3" ng-repeat="i in Items" ng-click="addOrderToList(i)">{{i.itemName}}</button>
</div>
</div>
<div class="">
<h2>Order Items</h2>
<ul>
<li ng-repeat="i in itemOrderList track by $index">
<p>{{i}}/<p>
<button ng-click="removeFromOrderToList($index)">Remove</button>
</li>
</ul>
</div>
</div>
</form>
I bet you need to specify you're using vars declared in $scope as so...
$scope.createOrder = function (order) {
var myJson = JSON.stringify($scope.itemOrderList);
order.orderPrice = $scope.totalItemPrices;
order.orderItems = myJson;
dataService.addOrder(order).then(function () {
$location.path('/');
});
};
I want to retain the selected check boxes as is even when I am
changing my search query. Initially I am posting some query in search
and selecting one of the resulted values, Now if I change my search
query, then New values will be my result. But I want to retain the
checkbox selected for the previous values...
`
//Demo of Searching and Sorting Table with AngularJS
var myApp = angular.module('myApp',[]);
myApp.controller('TableCtrl', ['$scope', function($scope) {
$scope.allItems = getDummyData();
$scope.resetAll = function()
{
$scope.filteredList = $scope.allItems ;
$scope.newEmpId = '';
$scope.newName = '';
$scope.newEmail = '';
$scope.searchText = '';
}
$scope.add = function()
{
$scope.allItems.push({EmpId : $scope.newEmpId, name : $scope.newName, Email:$scope.newEmail});
$scope.resetAll();
}
$scope.search = function()
{
$scope.filteredList = _.filter($scope.allItems,
function(item){
return searchUtil(item,$scope.searchText);
});
if($scope.searchText == '')
{
$scope.filteredList = $scope.allItems ;
}
}
$scope.resetAll();
}]);
/* Search Text in all 3 fields */
function searchUtil(item,toSearch)
{
/* Search Text in all 3 fields */
return ( item.name.toLowerCase().indexOf(toSearch.toLowerCase()) > -1 || item.Email.toLowerCase().indexOf(toSearch.toLowerCase()) > -1 || item.EmpId == toSearch
)
? true : false ;
}
/*Get Dummy Data for Example*/
function getDummyData()
{
return [
{EmpId:2, name:'Jitendra', Email: 'jz#gmail.com'},
{EmpId:1, name:'Minal', Email: 'amz#gmail.com'},
{EmpId:3, name:'Rudra', Email: 'ruz#gmail.com'}
];
}
.icon-search{margin-left:-25px;}
<br /> <br />
<div ng-app="myApp">
<div ng-controller="TableCtrl">
<div class="input-group">
<input class="form-control" ng-model="searchText" placeholder="Search" type="search" ng-change="search()" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-search"></span>
</span>
</div>
<table class="table table-hover data-table sort display">
<thead>
<tr>
<th class="EmpId"> <a href="" ng-click="columnToOrder='EmpId';reverse=!reverse">EmpId
</a></th>
<th class="name"> Name </th>
<th class="Email"> Email </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in filteredList | orderBy:columnToOrder:reverse">
<td><input type="checkbox" name="test" />{{item.EmpId}}</td>
<td>{{item.name}}</td>
<td>{{item.Email}}</td>
</tr>
</tbody>
</table>
<div class="row">
<div class="col-xs-3">
<input type="text" ng-model="newEmpId" class="form-control" placeholder="EmpId">
</div>
<div class="col-xs-3">
<input type="text" ng-model="newName" class="form-control" placeholder="Name">
</div>
<div class="col-xs-4">
<input type="email" ng-model="newEmail" class="form-control" placeholder="Email">
</div>
<div class="col-xs-1">
<button ng-click="add()" type="button" class="btn btn-primary">
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
</div>
</div> <!-- Ends Controller -->
</div>
`Fiddle
Try to add ng-model="item.selected" to your checkbox tag
<td><input ng-model="item.selected" type="checkbox" name="test" />{{item.EmpId}}</td>
Works for me, hope it helps.
Looks like this is happening because you are resetting the items here:
if($scope.searchText == '')
{
$scope.filteredList = $scope.allItems ;
}
and allItems doesn't tell anywhere if the checkbox needs to be selected on not. I would suggest you to update the code where you are creating the checkboxes, something like:
<td><input type="checkbox" name="test" ng-model=item.selected ng-checked=item.selected/>
Note that I have updated the item to have a 'selected' field which will tell if that item is selected or not(default could be false). While creating the checkbox I have linked the model using ng-model=item.selected
Updated fiddle at http://jsfiddle.net/3a3zD/194/
I have a html table that contains an ng repeat directive and two button.The first one will open a modal that contains a new form and let me create my user and then when i click save it will add it to the list.The second one is in the same original form and do the add a user.
What i did not understand why when i click on the first button which is in a different form i can not update the ng repeat however for the second one it's possible.
This is the code:
homepage.jsp
<body ng-app="myApp">
<div class="generic-container" ng-controller="UserController as ctrl">
<div id="createUserContent.jsp" ng-include="createUserContent"></div>
<table>
<tr>
<td>
<button type="button" class="btn btn-primary"
ng-click="ctrl.openCreateUser()">Create</button>
</td>
</tr>
</table>
<table class="table table-hover">
<thead>
<tr>
<th>ID.</th>
<th>Name</th>
<th>Address</th>
<th>Email</th>
<th width="20%"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="u in ctrl.users">
<td><span ng-bind="u.ssoId"></span></td>
<td><span ng-bind="u.firstName"></span></td>
<td><span ng-bind="u.lastName"></span></td>
<td><span ng-bind="u.email"></span></td>
</tr>
</tbody>
</table>
</div>
</body>
user_controller.js
'use strict';
App.controller('UserController', function ($scope, UserService, $window, $log, $uibModalStack,
$uibModal, $rootScope) {
var self = this;
self.users = [];
self.fetchAllUsers = function () {
console.log('----------Start Printing users----------');
for (var i = 0; i < self.users.length; i++) {
console.log('FirstName ' + self.users[i].firstName);
}
};
/**
this function will not work
**/
self.saveUser = function (user) {
self.users.push(user);
self.fetchAllUsers();
$log.log("saving user");
$uibModalStack.dismissAll();
};
/**
this function works fine
**/
self.addNewRow = function () {
var specialUser = {
id : 12,
firstName : 'john',
lastName: 'travolta',
homeAddress : {location:'chicago'},
email : 'trav#email.com'
};
self.users.push(specialUser);
$log.log("saving specialUser");
};
self.openCreateUser = function () {
var modalInstance = $uibModal.open({
animation : true,
templateUrl : 'createUserContent',
controller : 'UserController',
resolve : {
items : function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
self.fetchAllUsers();
});
createUserContent.jsp
<form role="form" ng-controller="UserController as ctrl" >
<div class="form-group">
<label for="FirstName">FirstName</label> <input type="FirstName"
ng-model="ctrl.user.firstName" class="form-control"
id="FirstName" placeholder="Enter FirstName" /> <label
for="lastName">lastName</label> <input type="lastName"
class="form-control" id="lastName"
ng-model="ctrl.user.lastName" placeholder="Enter lastName" />
<label for="email">Email address</label> <input type="email"
ng-model="ctrl.user.email" class="form-control" id="email"
placeholder="Enter email" />
</div>
<div class="form-group">
<label for="homeAddressLocation">Home Address</label> <input class="form-control"
ng-model="ctrl.user.homeAddress.location" id="homeAddressLocation"
placeholder="homeAddressLocation" />
</div>
<div class="form-group">
<label for="SSOId">SSOId</label> <input class="form-control"
ng-model="ctrl.user.ssoId" id="SSOId" placeholder="SSOId" />
</div>
<button type="submit" class="btn btn-default"
ng-click="ctrl.saveUser(ctrl.user)">Save</button>
<button type="submit" class="btn btn-default">Cancel</button>
</form>
Because of your modal template can't access your UserController object and doesn't show error because you used in modal template same controller so reloaded as new Ctrl doesn't refer parent Ctrl.
However better to use different controller and pass parent controller object to modal controller and then modal body can use all parent object. so you should pass parent object to modal controller.
When you include createUserContent.jsp popup file in your main file then no need to use ng-controller="UserController as ctrl" in your modal template you used in modalInstance controller : 'Ctrl',
like:
var modalInstance = $uibModal.open({
templateUrl: 'createUserContent.jsp',
controller: 'ModalCtrl', // ModalCtrl for modal
controllerAs:'modal', // as modal so no need to use in modal template
size: 'lg',
resolve: {
items: function () {
return $scope.items;
},
parent: function(){ // pass self object as a parent to 'ModalCtrl'
return self;
}
}
and ModalCtrl like:
.controller('ModalCtrl', ['parent', function (parent) {
this.parent = parent;
}]);
here used ModalCtrl for modal as modal so you can access parent object like: modal.parent.user
template like:
<form role="form" >
<div class="form-group">
<label for="FirstName">FirstName</label> <input type="FirstName"
ng-model="modal.parent.user.firstName" class="form-control"
id="FirstName" placeholder="Enter FirstName" />
.....
....
<button type="submit" class="btn btn-default"
ng-click="modal.parent.saveUser(modal.parent.user)">Save</button>
<button type="submit" class="btn btn-default">Cancel</button>
</form>
More details Visit PLUNKER DEMO
I can't seem to find why the "start" and "finish" part of my form isn't being rendered. This is the first time I've ever worked with AngularJS, and after following quite a few tuts online, I used to yo meanjs generator with the articles example. I then took the articles example and tried to port it over to this scheduling thing. It really doesn't matter though, I just want to know why the last two inputs in the form aren't being rendered in my view.
Any help is much appreciated
Here's the code for my view:
<section data-ng-controller="SchedulesController">
<div class="page-header">
<h1>New Schedule</h1>
</div>
<div class="col-md-12">
<form name="scheduleForm" class="form-horizontal" data-ng-submit="create()" novalidate>
<fieldset>
<div class="form-group" ng-class="{ "has-error": scheduleForm.title.$dirty && scheduleForm.title.$invalid }">
<label class="control-label" for="title">Title</label>
<div class="controls">
<input name="title" type="text" data-ng-model="title" id="title" class="form-control" placeholder="Title" required>
</div>
</div>
<div class="form-group">
<label class="control-label" for="content">Content</label>
<div class="controls">
<textarea name="content" data-ng-model="content" id="content" class="form-control" cols="30" rows="10" placeholder="Content"></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label" for="start">Start</label>
<div class="controls">
<input name="finish" value="" type="date" data-ng-model="start" class="form-control" required>
</div>
</div>
<div class="form-group">
<label class="control-label" for="finish">Finish</label>
<div class="controls">
<input name="finish" value ="" type="date" data-ng-model="finish", class="form-control" required>
</div>
</div>
<div class="form-group">
<input type="submit" class="btn btn-default">
</div>
<div data-ng-show="error" class="text-danger">
<strong data-ng-bind="error"></strong>
</div>
</fieldset>
</form>
</div>
</section>
Here's the code for my controller:
'use strict';
angular.module('schedules').controller('SchedulesController', ['$scope', '$stateParams', '$location', 'Authentication', 'Schedules',
function($scope, $stateParams, $location, Authentication, Schedules) {
$scope.authentication = Authentication;
$scope.create = function() {
var schedule = new Schedules({
title: this.title,
content: this.content,
start: this.start,
finish: this.finish
});
schedule.$save(function(response) {
$location.path('schedules/' + response._id);
console.log('hola!');
$scope.title = '';
$scope.content = '';
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
$scope.remove = function(schedule) {
if (schedule) {
schedule.$remove();
for (var i in $scope.schedules) {
if ($scope.schedules[i] === schedule) {
$scope.schedules.splice(i, 1);
}
}
} else {
$scope.schedule.$remove(function() {
$location.path('schedules');
});
}
};
$scope.update = function() {
var schedule = $scope.schedule;
schedule.$update(function() {
$location.path('schedules/' + schedule._id);
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
$scope.find = function() {
$scope.schedules = Schedules.query();
};
$scope.findOne = function() {
$scope.schedule = Schedules.get({
scheduleId: $stateParams.scheduleId
});
};
}
]);
Um... Well guys.... I don't know WHY this worked, and everything in me tells me this wasn't the problem, BUT:
Notice line
<input name="finish" value ="" type="date" data-ng-model="finish", class="form-control" required>
The "," was a mistake (I wrote a script that ported everything from articles into schedule, maintining code structure and just changing all mentions of [Aa]rticle{s} -> [Ss]chedule{s}, and this was left over in that (for some reason, don't know where it came in). Anyway, I deleted the comment and ran grunt build && grunt test && grunt and it worked. I'm now getting the correct render.
I am using a $modal in angular and, after a simple cycle of creating the modal and dismissing it, the main controller breaks with:
TypeError: object is not a function
at http://localhost:1337/bower_components/angular/angular.min.js:178:79
at f (http://localhost:1337/bower_components/angular/angular.min.js:195:177)
at h.$eval (http://localhost:1337/bower_components/angular/angular.min.js:113:32)
at h.$apply (http://localhost:1337/bower_components/angular/angular.min.js:113:310)
at HTMLAnchorElement.<anonymous> (http://localhost:1337/bower_components/angular/angular.min.js:195:229)
at http://localhost:1337/bower_components/angular/angular.min.js:31:225
at r (http://localhost:1337/bower_components/angular/angular.min.js:7:290)
at HTMLAnchorElement.c (http://localhost:1337/bower_components/angular/angular.min.js:31:207)
The main controller logic looks like:
(function(){
var app = angular.module('butler-user', ['ui.bootstrap']);
app.controller('UserController', ['$http', '$log', '$state', '$modal', '$scope', 'UserStatusService', function($http, $log, $state, $modal, $scope, UserStatusService) {
var self = this;
self.flash = '';
self.users = [];
self.newUser = {};
self.editUser = {};
$http.get('/user')
.success(function(data, status, headers, config) {
self.users = data;
})
.error(function(data, status, headers, config){
console.log('error getting data from /user');
$log.error("Error in get from /user: '"+config+"'");
});
var CreateUserModalCtlr = function ($scope, $modalInstance, userForm) {
$scope.userForm = {};
$scope.submitted = false;
$scope.validateAndCreate = function () {
console.log('Entering validateAndCreate()');
$scope.submitted = true;
if ($scope.userForm.$valid) {
console.log('Creating user with:'+JSON.stringify(self.newUser));
$http.post('/register', self.newUser)
.success(function(data, status, headers, config) {
console.log('response from /register'+data+' status:'+status)
if (status == 200) {
self.newUser = {};
$scope.submitted = false;
$http.get('/user')
.success(function(data, status, headers, config) {
self.users = data;
})
.error(function(data, status, headers, config){
$log.error("Error in get from /user: '"+config+"'");
});
$modalInstance.close('closed');
} else {
self.flash = 'Error creating new user';
}
})
.error(function(data, status, headers, config) {
console.log('Error in /register:'+status);
$modalInstance.close('closed');
});
}
};
$scope.cancelModal = function () {
console.log('Entering cancelModal()');
$modalInstance.dismiss('cancel');
};
};
self.addUser = function () {
var modalInstance = $modal.open({
templateUrl: '/admin/partials/CreateUser.html',
controller: CreateUserModalCtlr,
scope: $scope,
resolve: {
userForm: function () {
return $scope.userForm;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
The modal template looks like:
<div class="modal-header">
<h3>Create New User</h3>
</div>
<div class="modal-body">
<form name="userForm" novalidate>
<div class="form-group" ng-class="{ 'has-error' : userForm.firstName.$invalid && submitted }" >
<label>First Name</label>
<input name='firstName' class="form-control" type='text' ng-model='userCtlr.newUser.firstName' required ng-minlength=1>
<p ng-show="userForm.firstName.$invalid && submitted" class="help-block">First name is required.</p>
</div>
<div class="form-group" ng-class="{ 'has-error' : userForm.lastName.$invalid && submitted }">
<label>Last Name</label>
<input name='lastName' class="form-control" type='text' ng-model='userCtlr.newUser.lastName'required ng-minlength=1>
<p ng-show="userForm.lastName.$invalid && submitted" class="help-block">Last name is required.</p>
</div>
<div class="form-group" ng-class="{ 'has-error' : userForm.username.$invalid && !userForm.username.$pristine }">
<label>Username</label>
<input type="email" name="username" class="form-control" ng-model="userCtlr.newUser.username">
<p ng-show="userForm.username.$invalid && submitted" class="help-block">Enter a valid email address.</p>
</div>
<div class="form-group" ng-class="{ 'has-error' : userForm.username2.$invalid && !userForm.username2.$pristine }">
<label>Confirm Username</label>
<input type="email" name="username2" class="form-control" ng-model="userCtlr.newUser.username2">
<p ng-show="userForm.username2.$invalid && !userForm.username2.$pristine && submitted" class="help-block">Enter a valid email address.</p>
</div>
<div class="form-group" ng-class="{ 'has-error' : userForm.password.$invalid && !userForm.password.$pristine }">
<label>Password</label>
<input type="password" name="password" class="form-control" ng-model="userCtlr.newUser.password" required ng-minlength=8>
<p ng-show="userForm.password.$error.minlength && submitted" class="help-block">Password is too short.</p>
</div>
<div class="form-group" ng-class="{ 'has-error' : userForm.password2.$invalid && !userForm.password2.$pristine }">
<label>Confirm Password</label>
<input type="password" name="password2" class="form-control" ng-model="userCtlr.newUser.password2" required ng-minlength=8>
<p ng-show="userForm.password2.$error.minlength && submitted" class="help-block">Password is too short.</p>
</div>
<br><br>
{{registerCtlr.flash}}
</div>
<div class="modal-footer">
<button type="button" class="btn"
data-ng-click="cancelModal());">Cancel</button>
<button class="btn btn-primary"
data-ng-click="validateAndCreate();">Create User</button>
</div>
The main HTML page looks like:
<div clas='row' ng-controller='UserController as userCtlr'> <!-- Use bootstrap grid layout -->
<div class="col-md-8">
<table class='table table-striped'>
<thead>
<td>Email Address</td><td>First Name</td><td>Last Name</td>
</thead>
<tr ng-repeat='user in userCtlr.users'>
<td> <a ng-click='userCtlr.editUser(user)'>{{user.emailAddress}}</a></td>
<td> {{user.firstName}}</td>
<td> {{user.lastName}}</td>
</tr>
<tr>
</tr>
</table>
<form name='userForm' ng-submit='userCtlr.addUser()' novalidate>
<input type='submit' value='createNewUser'/>
</form>
</div>
</div>
I am new to the $modal (and Angular in general). I suspect that somehow dismissing the modal is breaking the main controller (or its variables), but I don't understand enough of how this all works to grog what I did wrong.
Any help is appreciated,
Charlie