setPristine is not a function - angularjs

I got my angular form all setup and working. The values are set after calling a response to a json request. The form is succesfully populated with the json response. After that i want to 'reset' the form, as in $scope.object.$setPristine. But i get an error:
$scope.object.$setPristine is not a function
I'm using angular 1.4.8.
Here is my HTML:
<div ng-app="myApp" ng-controller="formController" class="ng-scope">
<form name="object" ng-submit="submit()" method="post" action="" novalidate="" class="ng-pristine ng-valid">
<div class="form-group">
<label class="control-label" for="object_name">Name</label>
<input type="text" id="object_name" name="object[name]" ng-model="object.name" class="form-control ng-pristine ng-valid ng-touched" value="Object 2c">
</div>
<div class="form-group">
<label class="control-label" for="object_elements">Elements</label>
<select id="object_elements" name="object[elements][]" ng-model="object.elements" ng-options="opt.id as opt.name for opt in options | orderBy: "id"" class="form-control ng-pristine ng-untouched ng-valid" multiple="multiple"></select></div>
<div class="form-group">
<input ng-disabled="object.$pristine" class="btn btn-primary" value="Save" ng-click="submitForm()">
</div>
</form>
</div>
And here is my .js:
var app = angular.module('myApp', ["ngResource"]).controller('formController', function ($scope, $http, $location) {
var url = $location.absUrl() + '/json'
$http({
method: 'GET',
url: url
}).then(function (response) {
$scope.status = response.status;
$scope.data = response.data;
$scope.object = response.data;
$scope.object.$setPristine();
$('#modal-loading').modal('hide');
}, function (response) {
$scope.data = response.data || "Request failed";
$scope.status = response.status;
$('#modal-loading').modal('hide');
});
});

You overwrite $scope.object with a JSON response, of course it doesn't have any functions attached to it.
$scope.object = response.data;
$scope.object.$setPristine();
This is functionally the same as:
$scope.object = {of_course: "this doesn't work"};
$scope.object.$setPristine();
You probably just need to change your ng-models to reference $scope.data instead of $scope.object
ng-model="data.name"
and then not overwrite your form object.

My way is this...
<form name="newClntForm" id="newClnt" class="add(newClnt, newClntForm)">
<input type="text" class="form-control" ng-model="newClnt.name" placeholder="Contact Person Name" required >
</form>
And Controller Save Function is
function(newClnt, newClntForm){
angular.copy({},newClnt);
// newClntForm is form name
newClntForm.$setPristine();
newClntForm.$setUntouched();
};

Related

Connect Express nodemailer with Angular

I'm trying to make a contact form, and the server side is working pretty well. But I don't know how to connect Angular to the html form and send it with Express. Any would appreciate any help.
My Express
router.get('/sendQuote', function(req, res) {
var data = req.query;
var mailOptions = {
from: 'planacte#gmail.com', // sender address
name: data.contactName,
email: data.contactEmail,
to: data.email, // list of receivers
subject: "Request for a Quote from " + data.contactName, // Subject line
text: data.contactMsg, // plaintext body
html: '<p> email: ' + data.contactEmail +
'</p><p> phone: ' + data.contactPhone + '</p><br>'
+data.contactMsg // html body
};
console.log(mailOptions)
// send mail with defined transport object
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error);
}
console.log('Message sent: ' + info.response);
});
});
So, my html:
<form id="contact" class="contact-form" ng-submit="sendMail()" novalidate>
<div class="message"></div>
<div class="col-md-5 col-sm-5 col-xs-12 animated hiding" data-animation="slideInLeft">
<div class="form-group">
<input type="text" name="name" class="nameform form-control input-lg" placeholder="name" ng-model="contactName" required>
</div>
<div class="form-group">
<input type="email" name="email" class="emailform form-control input-lg" placeholder="email" ng-model="message.contactEmail" required>
</div>
<div class="form-group">
<input type="text" name="phone" class="phoneform form-control input-lg" placeholder="phone" ng-model="message.contactPhone">
</div>
</div>
<div class="col-md-7 col-sm-7 col-xs-12">
<div class="form-group">
<textarea name="message" class="messageform form-control input-lg" placeholder="custom text" ng-model="message.contactMsg" required></textarea>
</div>
</div>
<div class="col-md-7 col-sm-7 col-xs-12">
<input type="submit" class="btn btn-custom up form-button" value="Send Message">
And the main problem is here, how to glue Angular with HTML and Express. I can send emails, but get undefined in the fields of Name, Email and so on. :
app.controller('MainCtrl', ['$scope', '$interval', '$http', '$location', '$anchorScroll',
function($scope, $interval, $http, $location, $anchorScroll) {
$scope.sendMail = function () {
$scope.message = {};
$http.get('/send/sendQuote', $scope.message).
success(function(data, status, headers, config) {
// $scope.message = data.message;
console.log($scope.message)
});
}
}]);
I think you should start by making this request a POST and not a GET request.
router.post('/sendQuote', function(req, res) {
var data = req.body;
var mailOptions = {
from: 'planacte#gmail.com', // sender address
name: data.contactName,
email: data.contactEmail,
to: data.email, // list of receivers
subject: "Request for a Quote from " + data.contactName, // Subject line
text: data.contactMsg, // plaintext body
html: '<p> email: ' + data.contactEmail +
'</p><p> phone: ' + data.contactPhone + '</p><br>'
+data.contactMsg // html body
};
console.log(mailOptions)
// send mail with defined transport object
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error);
}
console.log('Message sent: ' + info.response);
res.send(200); // let the client know it sent ok.
});
Now, let's take a look at your Angular code. It seems you want the object $scope.message to hold your form fields data. You should define this as an object at the beginning of your controller.
app.controller('MainCtrl', ['$scope', '$interval', '$http', '$location', '$anchorScroll',
function($scope, $interval, $http, $location, $anchorScroll) {
$scope.message = {};
$scope.sendMail = function () {
//$scope.message = {}; -- this was clearing the object
$http.post('/send/sendQuote', $scope.message).
success(function(data, status, headers, config) {
// you can clear $scope.message if you want here
// $scope.message = data.message;
console.log($scope.message)
});
}
}]);
HTML had one ng-model not binding to the message object:
<form id="contact" class="contact-form" ng-submit="sendMail()" novalidate>
<div class="message"></div>
<div class="col-md-5 col-sm-5 col-xs-12 animated hiding" data-animation="slideInLeft">
<div class="form-group">
<input type="text" name="name" class="nameform form-control input-lg" placeholder="name" ng-model="message.contactName" required>
</div>
<div class="form-group">
<input type="email" name="email" class="emailform form-control input-lg" placeholder="email" ng-model="message.contactEmail" required>
</div>
<div class="form-group">
<input type="text" name="phone" class="phoneform form-control input-lg" placeholder="phone" ng-model="message.contactPhone">
</div>
</div>
<div class="col-md-7 col-sm-7 col-xs-12">
<div class="form-group">
<textarea name="message" class="messageform form-control input-lg" placeholder="custom text" ng-model="message.contactMsg" required></textarea>
</div>
</div>
<div class="col-md-7 col-sm-7 col-xs-12">
<input type="submit" class="btn btn-custom up form-button" value="Send Message">

Reset form on submit

I am submitting a form and then making all the field empty but it's not working. Form is getting submitted successfully but the fields are not getting reset. I am using angular-material for styling. Updated controller.
Html
<form name="myform">
<md-input-container>
<label for="name">Contact Name</label>
<input type="text" md-maxlength="20" required="" md-no-asterisk name="name" ng-model="info.name" md-autofoucs>
<div ng-messages="myform.name.$error" role="alert">
<div ng-message="required">This is required.</div>
<div ng-message="md-maxlength">The name has to be less than 20 characters long.</div>
</div>
</md-input-container>
<md-input-container>
<label for="phone">Phone Number</label>
<input type="text" name="phone" required md-no-asterisk ng-model="info.phone">
<div ng-messages="myform.phone.$error">
<div ng-message="required">This is required.</div>
</div>
</md-input-container>
<md-input-container>
<label for="email">Email</label>
<input type="text" name="email" ng-model="info.email">
</md-input-container>
<md-input-container>
<md-button class="md-primary" ng-click="saveit(info)">Save</md-button>
<md-button class="md-primary">Cancel</md-button>
</md-input-container>
</form>
**Function in Controller**
angular.module('contact', ['ui.router', 'ngMaterial', 'templates','ngMessages'])
.config(['$mdThemingProvider', '$stateProvider', function ($mdThemingProvider, $stateProvider) {
$mdThemingProvider.theme('default')
.primaryPalette('blue')
.accentPalette('orange');
$stateProvider
.state('home', {
url: '',
templateUrl: 'templates/home.html',
controller: 'MainCtrl as vm'
});
}]).controller('MainCtrl', function ($scope, $mdSidenav,$mdDialog,$mdToast, contacts) {
var vm = this;
$scope.searchText ="";
$scope.toggleSidenav = function(){
$mdSidenav('left').open();
};
contacts.getall().then(function(response){
console.log(response.data);
$scope.people = response.data;
});
$scope.saveit = function(detail, myform){
if (!detail.name || !detail.phone) { return ;}
contacts.add({
name: detail.name,
phone: detail.phone,
email: detail.email
});
$mdToast.show(
$mdToast.simple()
.content("ContactAdded!")
.position('top, right')
.hideDelay(2000)
);
$scope.people.push(detail);
$scope.info = {};
$scope.myform.$setPristine();
$scope.myform.$setUntouched();
};
$scope.showConfirm = function(ev, person) {
var confirm = $mdDialog.confirm()
.title('Are you sure?')
.ariaLabel('Lucky day')
.targetEvent(ev)
.ok('Please delete it!')
.cancel('I want to keep it.');
$mdDialog.show(confirm).then(function() {
contacts.deletethis(person.id).then(function(){
$mdToast.show(
$mdToast.simple()
.content("Deleted!")
.position('top, right')
.hideDelay(2000)
);
});
var index = $scope.people.indexOf(person);
$scope.people.splice(index,1);
}, function() {
$scope.status = 'You decided to keep your debt.';
});
}; });
<form name="myform">
<input type="text" ng-model="info.name">
<input type="text" ng-model="info.phone">
<input type="text" ng-model="info.email">
</form>
app.controller('MainCtrl', function($scope) {
$scope.info = {}; // name, phone, email
$scope.saveit = function() {
$scope.info.name = ''; // reset name
$scope.info.phone= ''; // reset phone
$scope.info.email= ''; // reset email
// reset form and disable error messages
$scope.myform.$setPristine();
$scope.myform.$setUntouched();
};
});
You are not using $scope and this for controller correctly. You can use $scope or controller as syntax to bind your scope with view.
I suggest you to read more about it here.
Update your saveit() function inside controller as below:
app.controller('MainCtrl', function($scope, $mdSidenav, $mdDialog, $mdToast) {
var vm = this;
vm.info = {};
//your rest the code
vm.saveit = function() {
//do your operations here
vm.info = {};
};
});
Update your html page as below:
<div ng-controller="MainCtrl as vm">
<form name="myform">
<md-input-container>
<label for="name">Contact Name</label>
<input type="text" ng-maxlength="20" required md-no-asterisk name="name" ng-model="vm.info.name" md-autofoucs>
</md-input-container>
<md-input-container>
<label for="phone">Phone Number</label>
<input type="text" name="phone" required md-no-asterisk ng-model="vm.info.phone">
</md-input-container>
<md-input-container>
<label for="email">Email</label>
<input type="text" name="email" ng-model="vm.info.email">
</md-input-container>
<md-input-container>
<md-button class="md-primary" ng-click="vm.saveit()">Save</md-button>
<md-button class="md-primary">Cancel</md-button>
</md-input-container>
</form>
</div>
Give $setPristine to reset the form after saving.
$scope.myform.$setPristine();
Another approach
app.controller('MainCtrl', function($scope, $mdSidenav, $mdDialog, $mdToast) {
var vm = this;
vm.info = {};
vm.saveit = function($event)
{
var form = angular.element($event.target).parent("form")[0];
if (form !== undefined) form.reset();
};
});
<div ng-controller="MainCtrl as vm">
<form name="myform">
<md-input-container>
<label for="name">Contact Name</label>
<input type="text" ng-maxlength="20" required md-no-asterisk name="name" ng-model="vm.info.name" md-autofoucs>
</md-input-container>
<md-input-container>
<label for="phone">Phone Number</label>
<input type="text" name="phone" required md-no-asterisk ng-model="vm.info.phone">
</md-input-container>
<md-input-container>
<label for="email">Email</label>
<input type="text" name="email" ng-model="vm.info.email">
</md-input-container>
<md-input-container>
<md-button class="md-primary" ng-click="vm.saveit($event)">Save</md-button>
<md-button class="md-primary">Cancel</md-button>
</md-input-container>
</form>
</div>
The answer below is missing one line of code to work properly
You can check the answer from another question right here:
https://stackoverflow.com/a/40267630/4767208

Angular model not injecting rest call when trying to UPDATE

So basically I am very new to angular and node so go easy on me. I have been building a REST API for a profile site and it obviously requires updating of posts. I have GET, DELETE and CREATE working but stuck with trying to get the current post object (from stateParams) to inject into the editor.
// Uses sateParams to get object id
.controller('EditPostCtrl', ['$scope', 'Post',
'$stateParams', '$state', function($scope, Post,
$stateParams, $state) {
$scope.action = 'Edit';
$scope.isDisabled = true;
$scope.post = Post.findById({ id: $stateParams.id })
.$promise
}])
<h1>Post Editor</h1>
<form name="form" ng-submit="submitForm()">
<div class="form-group">
<!-- If Error -->
<!-- Blog Title -->
<label>Title:</label>
<input type="text" class="form-control" placeholder="Example Title" autocomplete="off" required ng-model="post.title"></input>
<br />
<!--
<label>Author:</label>
<input type="text" class="form-control" autocomplete="off" placeholder="{{ author }}" required ng-model="post.author"></input>
<br />
-->
<!-- Date -->
<label>Date:</label>
<input type="date" class="form-control" required ng-model="post.date"></input>
<br />
<!-- Post Content -->
<label>Blog content:</label>
<div ng-controller="editorCtrl">
<textarea type="text" class="ck-editor" autocomplete="off" required ng-model="post.content"></textarea>
</div>
<div class="pull-right buttonspacer">
Cancel
<button class="btn btn-default btn-lg">{{ action }}</button>
</div>
</div>
</form>
.controller("EditPostCtrl", function($scope,$http){
$scope.submitForm = function(id) {
$http.post('/api/postid/' + id)
.success(function(data) {
$scope.action = 'Edit';
$scope.isDisabled = true;
console.log(data);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
});
in your angularjs,
you can use ng-click e.g.
<button class="btn btn-default btn-lg" ng-click="submitForm(post._id)">{{ action }}</button>
can you try this

AngularJS & Laravel - Wizard navigation

I am trying to create a multi form/wizard step navigation. I am using ng-switch to create the steps. But I got stuck, this is the relevant code:
HTML:
<div ng-controller="stepCtrl">
<div ng-switch="step">
<div ng-switch-when="1">
<div ng-controller="postAddressDataCtrl">
<form url="users/createaddress" ng-submit="add()">
<label class="input-label">
<span class="label-title">
Line 1
</span>
<input type="text" name="line-1" ng-model="line1" placeholder="Line 1">
</label>
<label class="input-label">
<span class="label-title">
Line 2
</span>
<input type="text" name="line-2" ng-model="line2" placeholder="Line 2">
</label>
<label class="input-label">
<span class="label-title">
City
</span>
<input type="text" name="city" ng-model="city" placeholder="City">
</label>
<label class="input-label">
<span class="label-title">
Postcode
</span>
<input type="text" name="postcode" ng-model="postcode" placeholder="Postcode">
</label>
<label class="input-label">
<span class="label-title">
Country
</span>
<input type="text" name="country" ng-model="country" placeholder="Country">
</label>
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
{{ Form::button('Save Address', array('type'=>'submit', 'class'=>'btn btn-primary', 'style' => 'width:100%;')) }}
</div>
</form>
</div>
<button ng-click="setStep(2)">Step 2</button>
</div>
<div ng-switch-when="2">
Step 2 - another form
<button ng-click="setStep(1)">Step 1</button>
<button ng-click="setStep(3)">Step 3</button>
</div>
<div ng-switch-when="3">
Step 3 - another form
<button ng-click="setStep(2)">Step 2</button>
</div>
</div>
</div>
Controllers:
stepCtrl
myApp.controller('stepCtrl',function($scope){
$scope.step = 1;
$scope.setStep = function(step){
$scope.step = step;
}
});
postAddressDataCtrl
myApp.controller('postAddressDataCtrl', ['$scope', '$http', 'CSRF_TOKEN', function($scope, $http, CSRF_TOKEN) {
$scope.urlpath = '{{ url('/') }}';
$scope.add = function() {
var line1 = $scope.line1;
var line2 = $scope.line2;
var city = $scope.city;
var postcode = $scope.postcode;
var country = $scope.country;
return $http({
url: "/users/createaddress",
method: "POST",
data: {
'line1': line1,
'line2': line2,
'city': city,
'postcode': postcode,
'country': country,
'_token': CSRF_TOKEN
},
}).success(function(data, status, headers, config) {
console.log(data);
if (data.status == 200) {
// move to the next step
}
}).error(function(data, status, headers, config) {
console.log(data);
});
};
}]);
How can I check if the data entered in the form are valid and if they are then to move in the next step with a single button?
How can I set the step equal to 2 when the data.status is equal to 200, so only then it will move on?
Use Angular's form validation. For example add required to your input field if you want to require the field and ng-minlength or ng-maxlength for character limits. You can also write custom validation if you need specific validation on certain fields.
To change the step you can increment your step variable inside ng-submit.
To increment only if your $http request is successful you can put it directly in your .success function.
<form url="users/createaddress" ng-submit="add()" novalidate>
<label class="input-label">
<span class="label-title">
Line 1
</span>
<input type="text" name="line-1" ng-model="line1" placeholder="Line 1" ng-minlength=3 ng-maxlength=20 required>
</label>
<button type="submit" class="btn btn-primary">Save Address</button>
</form>
postAddressDataCtrl
myApp.controller('postAddressDataCtrl', ['$scope', '$http', 'CSRF_TOKEN', function($scope, $http, CSRF_TOKEN) {
$scope.urlpath = '{{ url('/') }}';
$scope.add = function() {
var line1 = $scope.line1;
var line2 = $scope.line2;
var city = $scope.city;
var postcode = $scope.postcode;
var country = $scope.country;
return $http({
url: "/users/createaddress",
method: "POST",
data: {
'line1': line1,
'line2': line2,
'city': city,
'postcode': postcode,
'country': country,
'_token': CSRF_TOKEN
},
}).success(function(data, status, headers, config) {
console.log(data);
if (data.status == 200) {
// move to the next step
$scope.step += 1;
}
}).error(function(data, status, headers, config) {
console.log(data);
});
};
}]);

How to $http.post with payload in data?

How do I post data from a form in AngularJS?
<form data-ng-submit="doSomething()">
<input type="text" data-ng-input="do_obj.text"/>
<input type="email" data-ng-input="do_obj.email"/>
<input type="submit" value="Do something"/>
</form>
$scope.doSomething = function () {
$http({url: '/api/oauth2/register', method: 'POST', data: $scope.do_obj}
).then(function (data, status, headers, config) {
$log.info("data = ", data, "status = ", status,
"headers = ", headers, "config = ", config);
}
);
};
Plnkr (bootstrap styled)
See plunker code here
Changed data-ng-input into data-ng-model and updated data-ng-submit to pass in the model into the scope controller for processing.
HTML:
<body data-ng-app>
<div data-ng-controller="DoCtrl" class="container" style="margin: 15px">
<form data-ng-submit="doSomething(do_obj)" role="form" class="form-inline">
<div class="form-group">
<input type="text" data-ng-model="do_obj.bar"
placeholder="Enter text"
/>
</div>
<div class="form-group">
<input class="form-group" type="email"
data-ng-model="do_obj.email"
placeholder="Enter email"
/>
</div>
<div class="form-group">
<input class="btn btn-lg" type="submit"
data-ng-class="{'btn-info': hover}"
data-ng-mouseenter="hover = true"
data-ng-mouseleave="hover = false"
value="Do something"
/>
</div>
</form>
</div>
</body>
The syntax for posting is $http.post({url}, {payload});. I have updated your controller function to take in a parameter to pass to the post.
Controller code:
function DoCtrl($scope, $http, $log) {
$log.info("In DoCtrl");
$scope.do_obj = {};
$scope.doSomething = function (data) {
$http.post('/api/oauth2/register', data)
.success(function(successData){
console.log(successData);
});
}
}

Resources