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
Related
I am creating a form using angularjs and phpmailer. The input fields are binding and sending correctly, however, i am struggling to grab the title of the form, which is pretty important as the form will be a "service type" request.
HTML:
<div ng-controller="ContactCtrl">
<form ng-submit="submit(contactForm)" name="contactForm" method="post" class="service-form form-horizontal" role="form">
<h3 ng-model="formData.serviceName" id="serviceName">Request for {{ details.name }}</h3>
<div class="form-group" ng-class="{ 'has-error': contactForm.inputName.$invalid && submitted }">
<input ng-model="formData.inputName" type="text" class="inputText text-input" id="inputName" placeholder="Name" required>
</div>
<div class="form-group" ng-class="{ 'has-error': contactForm.inputEmail.$invalid && submitted }">
<input ng-model="formData.inputEmail" type="email" class="inputText text-input" id="inputEmail" placeholder="Email" required>
</div>
<div class="form-group" ng-class="{ 'has-error': contactForm.inputMessage.$invalid && submitted }">
<textarea ng-model="formData.inputMessage" rows="4" id="inputMessage" name="inputMessage" placeholder="Please add your requirements as per the 'Best Practice Checklist'"></textarea>
</div>
<button class="btn default btn-cancel" type="submit" onclick="switcher()">Cancel</button>
<button class="btn default" type="submit">Send</button>
</form>
<p ng-class="result">{{ resultMessage }}</p>
</div>
JS:
.controller('ContactCtrl', ['$scope', '$http', function($scope, $http) {
'use strict';
$scope.result = 'hidden'
$scope.resultMessage;
$scope.formData;
$scope.submitButtonDisabled = false;
$scope.submitted = false;
$scope.submit = function(contactform) {
$scope.submitted = true;
$scope.submitButtonDisabled = true;
if (contactform.$valid) {
var request = {
method: 'POST',
url: '/forms/contact.php',
data: $.param($scope.formData),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}
$http(request).then(function(data) {
console.log(data);
if (data) {
$scope.submitButtonDisabled = true;
$scope.resultMessage = data.message;
$scope.result = 'bg-success';
$scope.resultMessage = 'Thanks for the message! We will be in touch very soon.';
$scope.formData = {};
} else {
$scope.submitButtonDisabled = false;
$scope.resultMessage = data.message;
$scope.result = 'bg-danger';
$scope.resultMessage = 'Ooops! Something went wrong, Please fill out all the fields.';
}
});
} else {
$scope.submitButtonDisabled = false;
$scope.resultMessage = 'Ooops! Something went wrong, Please fill out all the fields.';
$scope.result = 'bg-danger';
}
}
}]);
so currently, I've got an h3 and have tried several other options, but the details.name isn't sending out, any help on this would be much appreciated. TIA.
We are working on form where user can upload 4 different photos. when i click choose file, it is calling to upload.php file and storing that file into uploadfiles directory.
but after file is uploaded unable to passing that particular file name to the angularjs.
Here is the UI Code
<head>
<script src="add-customer.js"></script>
<script type="text/javascript" src="angular-file-upload.js"> </script>
</head>
<body data-ng-cloak data-ng-app="AddCustomerApp" data-ng-controller="AddCustomerController as parentCtrl">
<section id="container">
<section id="main-content">
<section class="wrapper">
<div class="row mt">
<div class="col-lg-12">
<div class="form-panel">
<h4 class="mb">Add Customer</h4>
<form class="form-horizontal" role="form" id="AddCustomerForm" name="AddCustomerForm" autocomplete="off" enctype="multipart/form-data" novalidate="" data-ng-submit="AddCustomerData(AddCustomer)">
<div class="form-group">
<div class="col-sm-4">
<label for="firstname">First Name</label>
<input class="form-control" type="text" id="firstname" name="firstname" required placeholder="First Name" autofocus data-ng-model="AddCustomer.firstname">
</div>
</div>
<div controller="ChildController as childCtrl">
<div class="form-group" >
<div class="col-sm-6">
<label for="photo">Aadhaar Front</label>
<input type="file" class="form-control" id="adarfront" name="adarfront" required placeholder="Aadhaar Front" data-ng-model="AddCustomer.adarfront" ng-file-select="onFileSelect($files)">
</div>
<div class="col-sm-6">
<label for="photo">Aadhaar Back</label>
<input type="file" class="form-control" id="adarback" name="adarback" required placeholder="Aadhaar Back" data-ng-model="AddCustomer.adarback" ng-file-select="onFileSelect($files)">
</div>
</div>
<div class="form-group">
<div class="col-sm-6">
<label for="photo">Other ID Photo Front</label>
<input type="file" class="form-control" id="otheridfront" name="otheridfront" required placeholder="Other ID Photo Front" data-ng-model="AddCustomer.otheridfront" ng-file-select="onFileSelect($files)">
</div>
<div class="col-sm-6">
<label for="photo">Other ID Photo Back</label>
<input type="file" class="form-control" id="otheridback" name="otheridback" required placeholder="Other ID Photo Back" data-ng-model="AddCustomer.otheridback" ng-file-select="onFileSelect($files)">
</div>
</div>
</div>
<button type="submit" class="btn btn-theme" data-ng-disabled="AddCustomerForm.$invalid">Add</button>
</form>
</div>
</div>
</div>
</section>
</section>
</section>
</body>
Here is the AngularJs Code
var AddCustomer = angular.module("AddCustomerApp", ['angularFileUpload','ui.bootstrap'])
AddCustomer.controller("AddCustomerController", function ($scope, $timeout, $http, jsonFilter)
{
$scope.PersonalDetails = true;
var logResult = function (data, status, headers, config)
{
return data;
};
$scope.AddCustomerData = function (AddCustomer)
{
if($scope.AddCustomer.firstname==undefined || $scope.AddCustomer.adarfront==undefined || $scope.AddCustomer.adarback==undefined || $scope.AddCustomer.otheridfront==undefined || $scope.AddCustomer.otheridback==undefined)
{
alert("All fields are mendatory");
$scope.PersonalDetails = true;
$scope.WarningAlert = data;
}
else
{
$http.post('add-customer-process.php',{'firstname':$scope.AddCustomer.firstname,'adarfront':$scope.AddCustomer.adarfront,'adarback':$scope.AddCustomer.adarback,'otheridfront':$scope.AddCustomer.otheridfront,'otheridback':$scope.AddCustomer.otheridback})
.success(function (data, status, headers, config)
{
if(data=="Success")
{
$scope.PersonalDetails = true;
$scope.SuccessAlert = "Data added successfully";
$scope.AddCustomer = {};
$scope.AddCustomerForm.$setPristine();
$scope.AddCustomerForm.$setUntouched();
}
})
.error(function (data, status, headers, config)
{
$scope.WarningAlert = logResult(data, status, headers, config);
});
}
$scope.switchBool = function (value) {
$scope[value] = !$scope[value];
};
};
});
AddCustomer.controller('ChildController',function ($scope, $http, $upload)
{
$scope.parentCtrl.childCtrl = $scope.childCtrl;
$scope.onFileSelect = function($files)
{
$scope.message = "";
for (var i = 0; i < $files.length; i++)
{
var file = $files[i];
console.log(file);
$scope.upload = $upload.upload({
url: 'upload.php',
method: 'POST',
file: file
}).
success(function(data, status, headers, config)
{
$scope.message = data;
$scope.message=$scope.message.replace('\"', '');
$scope.childCtrl.message=$scope.message.replace('\"', '');
})
.error(function(data, status)
{
$scope.message = data;
});
}
};
});
kindly help Us. I'm newbie to AngularJS. Thank you in Advance.
In my response its showing a "Invalid username or password" message that is coming from server(node) if I enter invalid fields. But I don't know how to populate that in my template. I tried many examples but none of them worked for me. How to write services and controllers for it? TIA
Template:
<div ng-if="messages.error" role="alert" class="alert alert-danger">
<div ng-repeat="error in messages.error">{{error.msg}}</div>
</div>
<form name="frmRegister" ng-submit="login()" role="form">
<legend>Log In</legend>
<div class="form-group" ng-class="{ 'has-error': frmRegister.email.$dirty && frmRegister.email.$error.required }">
<label for="email">Email</label>
<input type="email" name="email" id="email" placeholder="Email" class="form-control" ng-model="user.email" required>
<span ng-show="frmRegister.email.$dirty && frmRegister.email.$error.required" class="help-block">Email is required</span>
</div>
<div class="form-group" ng-class="{ 'has-error': frmRegister.password.$dirty && frmRegister.password.$error.required }">
<label for="password">Password</label>
<input type="password" name="password" id="password" placeholder="Password" class="form-control" ng-model="user.password"
required>
<span ng-show="frmRegister.password.$dirty && frmRegister.password.$error.required" class="help-block">Password is required</span>
</div>
<button type="submit" id="submit" class="btn btn-success">Log in</button>
</form>
Controller:
angular.module('MyApp')
.controller('LoginCtrl', function($scope,$rootScope, $location, $auth, toastr, $http) {
$scope.login = function() {
$http ({
method : 'POST',
url: 'http://localhost:3000/onio/v1/login',
data : $scope.user
});
$auth.login($scope.user)
.then(function() {
toastr.success('You have successfully signed in!');
$location.path('/');
})
.catch(function(error) {
toastr.error(error.data.message, error.status);
});
};
$scope.authenticate = function(provider) {
$auth.authenticate(provider)
.then(function() {
$rootScope.currentUser = response.data.user;
toastr.success('You have successfully signed in with ' + provider + '!');
$location.path('/');
})
.catch(function(error) {
if (error.message) {
// Satellizer promise reject error.
toastr.error(error.message);
} else if (error.data) {
// HTTP response error from server
toastr.error(error.data.message, error.status);
} else {
toastr.error(error);
}
});
};
});
You need to bind the error data from the server to your scope so it can be used in your template. In your catch block try:
.catch(function(error) {
$scope.error_message = error.data.message
toastr.error(error.data.message, error.status);
});
Then in the html, you can bind that error message wherever you need it:
<div ng-if="error_message" role="alert" class="alert alert-danger">
<div>{{error_message}}</div>
</div>
Im trying to post input data with angular, but I don't know how to grab the data from the input fields.
Here is my HTML:
<div ng-controller="Test">
<div class="container">
<div class="col-sm-9 col-sm-offset-2">
<div class="page-header"><h1>Testar</h1></div>
<form name="userForm" ng-submit="submitForm(userForm.$valid)" novalidate> <!-- novalidate prevents HTML5 validation since we will be validating ourselves -->
<div class="form-group" ng-class="{'has-error' : userForm.name.$invalid && !userForm.name.$pristine, 'has-success' : userForm.name.$valid }">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="name" required>
<p ng-show="userForm.name.$invalid && !userForm.name.$pristine" class="help-block">Fel namn</p>
</div>
<div class="form-group" ng-class="{'has-error' : userForm.username.$invalid && !userForm.username.$pristine, 'has-success' : userForm.username.$valid && !userForm.username.$pristine}">
<label>Username</label>
<input type="text" name="username" class="form-control" ng-model="user.username" ng-minlength="3" ng-maxlength="8">
<p ng-show="userForm.username.$error.minlength" class="help-block">För kort</p>
<p ng-show="userForm.username.$error.maxlength" class="help-block">För långt</p>
</div>
<div class="form-group" ng-class="{'has-error' : userForm.email.$invalid && !userForm.email.$pristine, 'has-success' : userForm.email.$valid && !userForm.email.$pristine}">
<label>Email</label>
<input type="email" name="email" class="form-control" ng-model="email">
<p ng-show="userForm.email.$invalid && !userForm.email.$pristine" class="help-block">Ange korrekt e-post</p>
</div>
<button type="submit" class="btn btn-primary">Lägg till</button>
</form>
</div>
</div>
</div>
Here is my controller:
as.controller('Test', function($scope, $http, $rootScope)
{
$scope.submitForm = function(isValid) {
if(isValid)
{
$http.post($rootScope.appUrl + '/nao/test', {"data": $scope.userForm})
.success(function(data, status, headers, config) {
console.log(data);
}).error(function(data, status) {
});
}
};
});
A post is made when I hit the button, but the data that Is being sent looks like this:
{"data":{"name":{},"username":{},"email":{}}}
How can I take the data from all the input fields? Should I refer to userForm as I do in the controller?
I suggest to create one more $scope object - at beginning it will be empty:
$scope.form = {};
Every field will be a part of this object:
<input type="text" name="name" class="form-control" ng-model="form.name" required>
After send all fields you will have in object $scope.form.
jsFiddle: http://jsfiddle.net/krzysztof_safjanowski/QjNd6/
you have ng-model variables in scope:
$scope.name
$scope.user.username
$scope.email
you can all of these prefix with user. and then send with ajax $scope.user instead of $scope.userForm
or
try to send object which is copied by: angular.copy($scope.userForm)
You can have a property in your scope, say user. Have all your ng-model values be user.SOMETHING. This way you can easily send the $scope.user holding all the data, as in {data: $scope.user }.
I am using angular js directives for bootstrap. What i am trying for is to create an edit form on bootstrap modal when user clicks on edit button from list of items. Here is my code:
HTML:
<div class="modal-header">
<h3>Edit Template</h3>
</div>
<div class="modal-body">
<form name="form" class="form-horizontal" novalidate>
<fieldset>
<div class="span4" ng-class="smClass" ng-show="etemplate.status">{{etemplate.status}}</div>
<div class="control-group">
<label class="control-label" for="etemplateName">Name</label>
<div class="controls">
<input class="input-xlarge" id="etemplateName" ng-model="eTemplate.name" maxlength="150" type="text" required />
</div>
</div>
<div class="control-group">
<label class="control-label" for="etemplateDesc">Description</label>
<div class="controls">
<textarea id="templateDesc" id="etemplateDesc" ng-model="eTemplate.desc"></textarea>
</div>
</div>
<div class="center">
<input type="text" style="display:none;" ng-model="eTemplate.id" value="{{eTemplate.id}}" required />
<button type="button" ng-click="update(eTemplate)" class="btn btn-primary" ng-disabled="form.$invalid || isUnchanged(eTemplate)">Submit</button>
<button class="btn" ng-click="cancel()">Cancel</button>
</div>
</fieldset>
</form>
</div>
Controller:
controller('TemplateController', ['$scope', '$http', '$modal', function($scope, $http, $modal) {
var tmpId = '';
$scope.openEdit = function(id) {
tmpId = id;
var editTmpModalInstance = $modal.open({
templateUrl: 'editTemplateContent.html',
controller: 'ETModalInstance'
});
$http({
method: 'GET',
url: adminBaseUrl+'/get_template/',
params: {'id': tmpId}
}).
success(function(data, status, headers, config) {
$scope.$broadcast('EditTemplateDataReached', data);
}).
error(function(data, status, headers, config) {
});
}
}]).
controller('ETModalInstance', ['$scope', '$http', '$modalInstance', function($scope, $http, $modalInstance) {
$scope.emaster = {};
$scope.smClass = '';
$scope.eTemplate = {};
$scope.$on('EditTemplateDataReached', function(data) {
$scope.eTemplate = data;
$scope.$apply();
});
$scope.isUnchanged = function(eTemplate) {
return angular.equals(eTemplate, $scope.master);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.update = function(eTemplate) {
var strng = $.param(eTemplate);
};
}]).
My work around for achieving this is when user clicks on edit button id of selected item is passed in my controller which sends an ajax request to server and then fill the fields with respective values. However my fields are not populated when ajax data is returned.
Found the problem in my code i was using $scope for broadcasting and catching the data whereas i have to use $rootScope.
Wrong:
$scope.$broadcast('EditTemplateDataReached', data);
$scope.$on('EditTemplateDataReached', function(data) {
$scope.eTemplate = data;
$scope.$apply();
});
Correct:
$rootScope.$broadcast('EditTemplateDataReached', data);
$rootScope.$on('EditTemplateDataReached', function(e, data) {
$scope.eTemplate = data;
$scope.$apply();
});