Call a function from a directive to the controller - javascript

I am trying to implement a simple comment writing from client to server using angular.
Here is the HTML for the comment form:
<form id="commentsForm" name="commentsForm" ng-submit="submitComment()">
<fieldset>
<legend>Post a comment</legend>
<div class="form-group comment-group">
<label for="comment" class="control-label">Comment</label>
<div class="control-field">
<textarea class="form-control" cols="30" rows="5" name="comment" id="comment-textarea" tabindex="3" ng-model="c.comment" required></textarea>
</div>
</div>
<div class="form-group button-group">
<div class="control-field">
<button type="submit" class="btn btn-primary btn-comment" tabindex="4" >Post comment</button>
</div>
</div>
</fieldset>
</form>
And the controller I use with the "submitComment()" function:
'use strict';
// inject scope, services (CommentService)
//
angular.module('mean.groups').controller('CommentsCtrl', ['$scope','Global', 'CommentsService', function($scope, CommentsService) {
$scope.c = {};
console.log("controller is online");
$scope.submitComment = function (comment) {
console.log("activted submit comment function");
var postCommentData = {};
postCommentData.postingTime = new Date();
postCommentData.commentData = $scope.c.comment;
console.log("in controller:" + postCommentData);
CommentsService.postComment(postCommentData)
.then(function () {
$scope.commentsForm.$setPristine();
$scope.c = {};
console.log('posted');
});
};
}]);
And the directive I use wrap the html:
'use strict';
angular.module('mean.directives').directive('commentForm', function() {
return {
restrict: 'E',
templateUrl: 'comments/views/comment-form.html',
controller: 'CommentsCtrl',
controllerAs: 'commentsForm'
}
});
The service I use is a standard http.post service but I don't understand why the console.log() in the controller function is not triggered with the comment.
Thanks.

You aren't using the controller, to use the controller add the controllerAs object before the functions.
<form id="commentsForm" name="commentsForm" ng-submit="commentsForm.submitComment()">
<fieldset>
<legend>Post a comment</legend>
<div class="form-group comment-group">
<label for="comment" class="control-label">Comment</label>
<div class="control-field">
<textarea class="form-control" cols="30" rows="5" name="comment" id="comment-textarea" tabindex="3" ng-model="commentsForm.c.comment" required></textarea>
</div>
</div>
<div class="form-group button-group">
<div class="control-field">
<button type="submit" class="btn btn-primary btn-comment" tabindex="4" >Post comment</button>
</div>
</div>

Here is the answer, I just add :
link: function($scope, element, attrs) {
$scope.submitComment = function () {
//my code logic ...
}
}
And changed the replace to false:
replace: false;

Related

AngularJS 1.6.8: Unable to submit form and display success message

I have a simple query submission form with name, email and query fields and a component with a controller function having the submit function to submit the form.
I am using ng-submit directive in the <form></form> tag to submit the user input and display a success message on submission.
below is the code for the respective files.
contact.html
<div ngController="contactController as vm">
<div class="heading text-center">
<h1>Contact Us</h1>
</div>
<div>
<form class="needs-validation" id="contactForm" novalidate method="post" name="vm.contactForm" ng-submit="saveform()">
<div class="form-group row">
<label for="validationTooltip01" class="col-sm-2 col-form-label">Name</label>
<div class="input-group">
<input type="text" class="form-control" id="validationTooltipName" placeholder="Name" ng-model="vm.name" required>
<div class="invalid-tooltip">
Please enter your full name.
</div>
</div>
</div>
<div class="form-group row">
<label for="validationTooltipEmail" class="col-sm-2 col-form-label">Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="validationTooltipUsernamePrepend">#</span>
</div>
<input type="email" class="form-control" id="validationTooltipEmail" placeholder="Email"
aria-describedby="validationTooltipUsernamePrepend" ng-model="vm.email" required>
<div class="invalid-tooltip">
Please choose a valid email.
</div>
</div>
</div>
<div class="form-group row">
<label for="validationTooltip03" class="col-sm-2 col-form-label">Query</label>
<div class="input-group">
<input type="text" class="form-control" id="validationTooltipQuery" ng-model="vm.query" placeholder="Query" required>
<div class="invalid-tooltip">
Please write your Query.
</div>
</div>
</div>
<div class="btn-group offset-md-5">
<button class="btn btn-primary" type="submit">Submit</button>
<button class="btn btn-default" type="button" id="homebtn" ng-click="navigate ('home')">Home</button>
</div>
</form>
<span data-ng-bind="Message" ng-hide="hideMessage" class="sucessMsg"></span>
</div>
</div>
contact.component.js
angular.module('myApp')
.component('contactComponent', {
restrict: 'E',
$scope:{},
templateUrl:'contact/contact.html',
controller: contactController,
controllerAs: 'vm',
factory:'userService',
$rootscope:{}
});
function contactController($scope, $state,userService,$rootScope) {
var vm = this;
$scope.navigate = function(home){
$state.go(home)
};
$scope.saveform = function(){
$scope.name= vm.name;
$scope.email= vm.email;
$scope.query= vm.email;
$scope.hideMessage = false;
$scope.Message = "Your query has been successfully submitted."
};
$scope.user = userService;
};
//localStorage code
function userService($rootScope) {
var service = {
model: {
name: '',
email: '',
query:''
},
SaveState: function () {
sessionStorage.userService = angular.toJson(service.model);
},
RestoreState: function () {
service.model = angular.fromJson(sessionStorage.userService);
}
}
$rootScope.$on("savestate", service.SaveState);
$rootScope.$on("restorestate", service.RestoreState);
return service;
$rootScope.$on("$routeChangeStart", function (event, next, current) {
if (sessionStorage.restorestate == "true") {
$rootScope.$broadcast('restorestate'); //let everything know we need to restore state
sessionStorage.restorestate = false;
}
});
//let everthing know that we need to save state now.
window.onbeforeunload = function (event) {
$rootScope.$broadcast('savestate');
};
};
UPDATE: On Submit, When I check the response in network tab in dev tools, I do not see the submitted values. All I see is the markup.
In your template, the name of the method is saveform:
ng-submit="saveform()"
But in your controller, it's save:
$scope.save = function() { ... }
Rename it to saveform:
$scope.saveform = function() { ... }

Controller on Modal not working on AngularJS

I have a main users page with users, if you select a user, a modal is opened and should show the user information.
The problem is that the $scope doesn't seem to be working, as it doesn't show the user data on the modal. But if I show that user data anywhere on the main users page, it works fine.
I have this controller:
function userController($scope, $modal, $http, $rootScope) {
var usrCtrl = this;
$scope.users = null;
$scope.openUserForm = function () {
var modalInstance = $modal.open({
templateUrl: 'views/modal_user_form.html',
controller: userController,
windowClass: "animated flipInY"
});
};
var session = JSON.parse(localStorage.session);
$http({
method: 'GET',
url: $rootScope.apiURL+'getAllClientUsers/'+session,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function(response){
if(response.ErrorMessage === null && response.Result !== null){
$scope.users = response.Result;
}
});
//**This is the code that opens the modal
$scope.editViewUser = function(user){
for (var key in $scope.users) {
if($scope.users[key].SecUserId === user){
$scope.selectedUser = $scope.users[key];
}
}
$scope.openUserForm();
};
};
And this modal:
<div ng-controller="userController">
<div class="inmodal">
<div class="modal-header">
<h4 class="modal-title">Create or Edit User</h4>
<small class="font-bold">Use this modal to create or edit a user</small>
</div>
<div class="modal-body">
<form method="get" class="form-horizontal">
<div class="form-group"><label class="col-sm-2 control-label">Nombre</label>
<div class="col-sm-10"><input ng-model="selectedUser.FirstName" type="text" class="form-control"></div>
</div>
<div class="form-group"><label class="col-sm-2 control-label">Apellido</label>
<div class="col-sm-10"><input ng-model="selectedUser.LastName" type="text" class="form-control"></div>
</div>
<div class="form-group"><label class="col-sm-2 control-label">Usuario</label>
<div class="col-sm-10"><input ng-model="selectedUser.UserName" type="text" class="form-control"></div>
</div>
<div class="form-group"><label class="col-sm-2 control-label">Email</label>
<div class="col-sm-10"><input ng-model="selectedUser.Email" type="email" class="form-control"></div>
</div>
<div class="form-group"><label class="col-sm-2 control-label">Activo</label>
<div class="col-sm-10">
<div><label> <input ng-model="selectedUser.FirstName" type="checkbox" value=""></label></div>
</div>
</div>
<div class="form-group"><label class="col-sm-2 control-label">Email Verificado</label>
<div class="col-sm-10">
<div><label> <input ng-model="selectedUser.FirstName" type="checkbox" value=""></label></div>
</div>
</div>
<div class="form-group"><label class="col-sm-2 control-label">Privilegios</label>
<div class="col-sm-10">
<select class="form-control m-b" name="account">
<option ng-repeat="priv in selectedUser.EffectivePrivileges">{{ priv }}</option>
</select>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-white" ng-click="cancel()">Close</button>
<button type="button" class="btn btn-primary" ng-click="ok()">Save changes</button>
</div>
</div>
</div>
I tried injecting the controller and also using the ng-controller, and scope property for modal.
What am I missing?
The problem is that modal template is compiled in the scope which doesn't inherit from your $scope. To make a connection between them you can tell modal to create a new child scope of your scope:
$scope.openUserForm = function () {
var modalInstance = $modal.open({
scope: $scope, // <----- add this instruction
templateUrl: 'views/modal_user_form.html',
controller: userController,
windowClass: "animated flipInY"
});
};
Generally, the modal would have its own controller rather than point to the controller that its called from. You would inject the model (selectedUser) into the modal controller, work on it, then pass it back to parent. Also, you can give user option to cancel in which case no changes are made to parent controller model.
Modal controller:
app.controller('UserModalController', [
'$scope',
'$modalInstance',
'selectedUser',
function ($scope, $modalInstance, selectedUser) {
$scope.selectedUser = selectedUser;
$scope.cancel= function () {
// user cancelled, return to parent controller
$modalInstance.dismiss('cancel');
};
$scope.save = function () {
// close modal, return model to parent controller
$modalInstance.close($scope.selectedUser);
};
]);
Changes to main controller:
var modalInstance = $modal.open({
templateUrl: 'views/modal_user_form.html',
controller: 'UserModalController',
windowClass: "animated flipInY",
resolve: {
selectedUser: function() {
return $scope.selectedUser;
}
}
});
modalInstance.result.then(function(updatedUser) {
// deal with updated user
}, function() {
// modal cancelled
});

Can't access form inside AngularJS controller

Can't access form variable from my controller, when i try to access it by $scope.locationForm i've got 'undefined', but when i call console.log($scope) i can see in console there have loactionForm.
My HTML code
<div ng-controller="LocationsController as ctrl">
<form class="form-inline" name="locationForm">
<div class="form-group">
<!-- <div class="input-group"> -->
<label for="location-name">Название населенного пункта</label>
<input required
name="name"
ng-model="ctrl.location.name" type="text" class="form-control" id="location-name" placeholder="Название населенного пункта">
<label for="location-name">Район</label>
<select required
name="region_id"
ng-model="ctrl.location.region_id"
ng-options="region.id as region.name for region in ctrl.regions" class="form-control" placeholder="Название района"></select>
<input ng-click="ctrl.save()"
ng-disabled="locationForm.$invalid" type="submit" class="btn btn-default" value="Cохранить">
<a class="btn btn-default" ng-click="ctrl.reset()" ng-show="locationForm.$dirty">Сброс</a>
<!-- </div> -->
</div>
</form>
My Controller code:
function LocationsController($scope, Location, Region, $q) {
var lc = this,
l_index;
lc.form ={};
lc.regions = lc.locations = [];
lc.regions = Region.query();
lc.regions.$promise.then(function(data) {
lc.locations = Location.query();
});
lc.getRegion = function (id) {
return lc.regions.filter(function(obj) {
return obj.id == id;
})[0].name;
};
console.log($scope);
// console.log($scope.locationForm);
lc.reset = function () {
lc.location = new Location;
}
lc.reset();
};
The problem is when the LocationsController is initialized the form element is not yet compiled. So one possible hack is to use a timeout like
function LocationsController($scope, Location, Region, $q, $timeout) {
//then later
$timeout(function(){lc.reset();})
}

how to pass data from modal to function

I have a modal form that has several inputs text form control. How do I pass the data to post to the database so that ng-grid gets updated?
do I call my ajax create function within the $scope.open controller section? or resolve?
$scope.open = function (size) {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});
};
}]);
the create function
$scope.createMedicalServices = function(){
var providerMedicalServiceAttributes = {};
providerMedicalServiceAttributes.cash_price = $scope.cash_price
providerMedicalServiceAttributes.average_price = $scope.average_price
providerMedicalServiceAttributes.service = $scope.service
var medicalServicesAttributes = {};
medicalServicesAttributes.description = $scope.description
medicalServicesAttributes.service = $scope.service
var newMedicalService = ProviderMedicalService.create(providerMedicalServiceAttributes);
$scope.provider_medical_services.push(newMedicalService);
ProviderMedicalService.update(providerMedicalServiceAttributes, '/providers/services');
};
create function from factory (factory does delete, querying and create)
ProviderMedicalService.prototype.create = function(attr){
return this.service.save(attr);
}
the html for the modal form
<div ng-controller="ModalDemoCtrl">
<script type="text/ng-template" id="myModalContent.html">
<div class="header-modal">
<h3>Add Service</h3>
</div>
<div class="modal-body">
<form name="myForm" novalidate ng-submit="submit()">
<div class="row well-text-padding">
<div class="col-md-3 modal-form-tag">CPT Code</div>
<div class="col-md-6">
<input type="text" class="form-control form-control-modal" ng-model="CPT_code" placeholder="CPT Code">
</div>
</div>
<label class="checkbox modal-check-box">
<input type="checkbox" ng-model="No_CPT_code">Service does not have a associated CPT Code
</label>
<div class="row well-text-padding">
<div class="col-md-3 modal-form-tag">Description</div>
<div class="col-md-6">
<textarea class="form-control form-control-modal" rows="3" ng-model="Description" placeholder="Add a Description"></textarea>
</div>
</div>
<div class="row well-text-padding">
<div class="col-md-3 modal-form-tag">Average Cost</div>
<div class="col-md-6">
<input type="text" class="form-control form-control-modal" ng-model="Average_cost" placeholder="$">
</div>
</div>
<div class="row well-text-padding">
<div class="col-md-3 modal-form-tag">Offered Price</div>
<div class="col-md-6">
<input type="text" class="form-control form-control-modal" ng-model="Offered_price" placeholder="$">
</div>
</div>
<div class="btn-row2 modal-button-row">
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
<button class="btn btn-primary" type="submit">Add Service</button>
</div>
</script>
You can make the POST request to server when clicked Add Service, or you can pass your data from modal to your main controller through $scope.$close().
Example as below:
In modal controller
var data = {
CPT_code: $scope.CPT_code,
No_CPT_code: $scope.No_CPT_code,
Description: $scope.Description,
Average_cost: $scope.Average_cost,
Offered_price: $scope.Offered_price
};
$scope.$close(data); // pass the data through modal close event
Then in your main controller by using the promise to get the data
$scope.open = function (size) {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
}).result.then(function (response) {
var data = response; // here is your data from your modal
});
};
Hope this helps.

How to submit a form using angular ui bootstrap's modal and csrf

I would like to submit a form using Angular UI Bootstrap's modal. I'm instantiating the modal like:
AdminUsers.factory('ProjectsService', ['$resource', function($resource) {
return $resource('/api/users?sort=createdAt desc');
}]).controller('AdminUsersCtrl', ['ProjectsService', '$scope', '$http', '$modal', '$log', function(ProjectsService, $scope, $http, $modal, $log, $modalInstance) {
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: '../templates/userModal.html',
controller: function($scope, $modalInstance) {
$scope.user = {};
$scope.ok = function () { $modalInstance.close($scope.user); };
$scope.cancel = function () { $modalInstance.dismiss('cancel'); };
},
resolve: {
items: function () {
return $scope.user;
}
}
});
modalInstance.result.then(function (user) {
$scope.user = user;
$http.post('/api/users/new', $scope.user).success(function() {
$scope.users.unshift($scope.user);
});
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
}
PS: Please note the controller above does have other methods that is not being displayed above.
The code in my userModal.html is:
<div class="modal-header">
<button type="button" class="close" ng-click="cancel()">×</button>
<h6>New customer</h6>
</div>
<div class="modal-body">
<form class="form-horizontal fill-up separate-sections">
<div>
<label>Name</label>
<input type="text" ng-model="user.name" placeholder="Name" />
</div>
<div>
<label>Email</label>
<input type="email" ng-model="user.email" placeholder="Email" />
</div>
<div>
<label>Admin</label>
<select class="form-control" ng-model="user.admin"
ng-options="option as option for option in [true, false]"
ng-init="user.admin=false"></select>
<input type="hidden" name="user.admin" value="{{user.admin}}" />
</div>
<div>
<label>Password</label>
<input type="password" ng-model="user.password" placeholder="Password" />
</div>
<div>
<label>Password confirmation</label>
<input type="password" ng-model="user.confirmation" placeholder="Password confirmation" />
</div>
<div class="divider"><span></span></div>
<div class="divider"><span></span></div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-blue btn-lg" ng-click="ok()">Save</button>
<button class="btn btn-default btn-lg" ng-click="cancel()">Cancel</button>
<input type="hidden" name="_csrf" value=_csrf />
</div>
The problem lies with the hidden input. I need to submit the csrf with form to the server but I don't know how. If this was a jade template I could simply:
input(type="hidden", name="_csrf", value=_csrf)
and Sails/Express would deal with the rest. But because this is a html template used by Angular only, I don't know how to access the _csrf key. I've tried looking into window.document.cookie however it returned undefined.
Can anyone shed some light on this?
Many thanks

Categories