angular js: Unable to validate a textarea - angularjs

fellas!
I'm trying to validate a text area upon clicking a link. Thing is, It's not coming inside a form. And when a user clicks a link, content entered in the text area should be posted (saved to database).
I wrote a validation for that. And unfortunately, it's not working and I'm able to make blank posts. I'm trying to prevent blank post posting. I have recreated the form and the controller in a fiddle. Link I'll provide down. but before that, take a look at my html and js code.
HTML
<div ng-app="myApp" ng-controller="myMap">
<div class="post-textarea" ng-class="{ 'has-error': vm.currentPost.content.$dirty && vm.currentPost.content.$error.required }">
<textarea class="form-control" rows="3" ng-model="vm.currentPost.content" required></textarea>
<a ng-click="vm.addPost(vm.currentPost.content,vm.currentPost.$valid)">Clik to Post and validate</a>
</div>
</div>
JavaScript
angular.module('myApp', [])
.factory('myService', function($http) {
var baseUrl = 'api/';
return {
postCurrentPost: function(newPost) {
var dataPost = {
newPost: newPost
};
return $http({
method: 'post',
url: baseUrl + 'postCurrentPost',
data: dataPost,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
}
};
})
.controller('myMap', function(myService, $http, $scope) {
var vm = this;
var userObject;
// Add a post
vm.addPost = function(newPost, isValid) {
if (isValid) {
var currentPost = vm.currentPost;
currentPost.content = ""; //clear post textarea
myService.postCurrentPost(newPost).success(function(data) {
vm.posts = data;
});
} else {
alert('Validation not working');
}
};
//Check validation
$scope.getError = function(error, name) {
if (angular.isDefined(error)) {
if (error.required && name == 'vm.currentPost.content') {
return "This field is required";
}
}
}
});
And here's a FIDDLE.

Name of the form input element should be used instead of model value.
https://docs.angularjs.org/api/ng/directive/form
<div ng-app="myApp" ng-controller="myMap">
<form name="formContent">
<div class="post-textarea" ng-class="{ 'has-error': formContent.content.$dirty && formContent.content.$error.required }">
<textarea name='content' class="form-control" rows="3" ng-model="vm.currentPost.content" required></textarea>
<a ng-click="vm.addPost(vm.currentPost.content,vm.currentPost.$valid)">Clik to Post and validate</a>
</div>
</form>
Content is dirty: {{formContent.content.$dirty}}
<br>
Content has required: {{formContent.content.$error.required}}
</div>

Related

How to pass data-plugin="timepicker" value to controller in angularJS

I have code to pass date and time to controller.
Here is HTML code,
<div class="page-content" ng-app="app">
<div ng-controller="postAppoinmentCtr as ctrl" class="panel-body">
<form ng-submit="submitForm()" id="form1">
<input name="time" ng-model="time" type="text" class="form-control" ng-model="time" data-plugin="timepicker" autocomplete="off"/>
<input name="date" ng-model="date" type="text" class="form-control" data-plugin="datepicker"/>
<input..ng-model="type"...></input>
<input..ng-model="Description"...></input>
<button ...>
</form>
</div>
</div>
Here is angular js part
var app = angular.module('app', []);
app.controller('postAppoinmentCtr', function($scope, $http, $location) {
$scope.submitForm = function(){
var url = $location.absUrl() + "/addAppoinment";
alert(url);
var config = {
headers : {
'Content-Type': 'application/json;charset=utf-8;'
}
}
var data = {
type: $scope.type,
date: $scope.date,
time: $scope.time,
description: $scope.description
};
$http.post(url, data, config).then(function (response) {
$scope.postResultMessage = "Sucessful!";
}, function (response) {
$scope.postResultMessage = "Fail!";
});
$scope.type = "";
$scope.date = "";
$scope.time ="";
$scope.description ="";
}
});
When click the button type and description pass to controller. But date and time not. I can do this using
<input id="date-birth" class="form-control" type="date" ng-model="date">
this line. But I need to use data-plugin="datepicker" .
I'm new one for the angularjs and I try to many ways for solve this problem.
Please give me some answer this. Thanks in advance.

AngularJS toggle ng source value on click

I need some help about toggling ng-src between for example: image.jpg and image-active.jpg, but I have some issues because I need to active that with AngularJS.
This is the scenario: I called an API data from swagger and use ng-repeat to display images in html.
HTML
<div class="input-group interests-list">
<div class="checkbox" ng-repeat="interest in interests">
<label>
<div class="interest-icon">
<img src="{{interest.iconUrl}}" ng-click="changeImage()">
</div>
<input style="display: none;" type="checkbox" value="{{interest.name}}">
{{interest.name}}
</label>
</div>
</div>
Service
this.getInterests = function () {
var deferred = $q.defer();
var req = {
method: 'get',
url: 'http://customdealwebapi20180125110644.azurewebsites.net/api/Interests'
}
$http(req).then(function (response) {
deferred.resolve(response.data);
}, function (err) {
console.log(err)
});
return deferred.promise;
}
Controller
TestService.getInterests().then(function (data) {
$scope.interests = data;
});
and everything works fine
Now I want to achieve when someone click on the image, ng-src should be changed to image-active.jpg, and on the next click image should be changed to default value (image.jpg)
I know how to achieve through jQuery, like this
$(".interests-list .checkbox label input[type='checkbox']").change(function () {
var selectedIcon = $(this).val();
if (this.checked) {
console.log($(this).prev())
$(this).prev().find("img").attr("src", "assets/img/home/icons/" + selectedIcon + "-active.png");
} else {
$(this).prev().find("img").attr("src", "assets/img/home/icons/" + selectedIcon + ".png");
}
});
Thank you
You can either use ng-show
<div class="checkbox" ng-repeat="interest in interests" ng-init="interest.active = false">
<label>
<div class="interest-icon">
<img ng-show="interest.active == true" src="active.png" ng-click="interest.active = !interest.active">
<img ng-show="interest.active == false" src="other.png" ng-click="interest.active = !interest.active">
</div>
</label>
</div>
or you can pass interest to your click function and set image src in your controller
<img src="{{interest.iconUrl}}" ng-click="changeImage(interest)">
$scope.changeImage = function(interest){
if(checked)
interest.iconUrl = "active.png";
else
interest.iconUrl = "other.png";
}

AngularJS Textarea If data Is loading

I have a textarea that relies upon a dropdown menu to populate. When the dropdown is changed, a file is pulled and the contents are loaded to the textarea.
While the textarea is loading, it just says [object Object]. I'd like it to be a bit nicer than that. Something like 'Loading...'.
I cant find away to specifically do this with a textarea though.
Another wrench in the wheel is that the Save functionality actually relies upon the value of the text area to save, so I cant just alter the content of the text area to display 'Saving...' otherwise the content that is written to the file is just 'Saving...'.
Here is the code:
View
<div id="Options" class="panel-collapse collapse">
<div class="panel-body">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon input-sm">Config Select</span>
<select ng-change="update()" ng-model="configFileName" class="form-control input-sm">
<option>--</option>
<option ng-repeat="conf in configList" value="{{conf.name}}">{{conf.name}}</option>
</select>
</div>
</div>
<div class="form-group">
<div class="input-group">
<td style="padding-bottom: .5em;" class="text-muted">Config File</td><br />
<textarea id="textareaEdit" rows="20" cols="46" ng-model="configFileContent"></textarea>
<input type="button" ng-click="updateConfig()" style="width: 90px;" value="Save"></button>
</div>
</div>
</div>
</div>
JS
$scope.update = (function(param) {
$scope.configFileContent = 'Loading...';
$scope.configFileContent = $api.request({
module: 'Radius',
action: 'getConfigFileContent',
method: 'POST',
data: $scope.configFileName
}, function(response) {
$timeout(function() {
console.log('got it');
$scope.configFileContent = response.confFileContent;
}, 2000);
});
});
$scope.updateConfig = (function(param) {
var data = [$scope.configFileName, $scope.configFileContent];
var json = JSON.stringify(data);
$scope.configFileContent = $api.request({
module: 'Radius',
action: 'saveConfigFileContent',
method: 'POST',
data: json
}, function(response) {
$timeout(function() {
console.log('Saved!');
$scope.update();
}, 2000);
});
});
<script>
var app = angular.module("myShoppingList", []);
app.controller("myCtrl", function($scope, $timeout) {
$scope.update = function() {
if ($scope.selectedData === '') {
$scope.someData = '';
return;
}
// do http response
var data = 'dummy file text from server';
$scope.xhr = false;
$scope.msg = 'loading...';
// simulating fetch request
$timeout(function() {
$scope.xhr = true;
$scope.content = data;
}, 3000);
}
});
</script>
<div ng-app="myShoppingList" ng-controller="myCtrl">
<select ng-model="selectedData" ng-change="update()">
<option selected="selected" value="">Select data</option>
<option value="foo">Fetch my data</option>
</select>
<br><br><br>
<textarea rows="5" cols="20" ng-model="someData" ng-value="xhr === false ? msg : content">
</textarea>
</div>
You can use a scope variable to detect the completion of promise request of xhr and simulate a loading... message.
As for save, i recommend not to use such approach of displaying message inside textarea and instead create another directive/component to detect the loading and saving request completion which is reusable and separates business logic keeping controller thin.

How to repopulate user entered form values in angular JS when the REST API call fails

I am having an angular js form with dropdowns and text boxes ,on submitting the form I am planning to call an REST API to save the user entered values. i Would like to know if in case the insert fails, how to re populate the user entered form values in the frontend with an error message
Here is one way you could go about making a copy and re-setting the user deets on. Hope it helps. Here's a Codepen for the below code.
function exampleFactory($http) {
//placeholder exampleFactory
console.log('exampleFactory');
function login() {
return {
data: console.log('data saved')
};
}
return {
login: login
};
}
function exampleController($scope, exampleFactory, $timeout) {
var copyOfUserDeets;
$scope.userForm = {};
$scope.submit = function(userDeets) {
copyOfUserDeets = angular.copy(userDeets);
$scope.userForm = {};
// exampleFactory
// .login(userDeets)
// .then(function(resp) {
// $scope.userForm = {};
// })
// .catch(function(error) {
// $scope.userForm = copyOfUserDeets;
// });
$timeout(function() {
$scope.userForm = copyOfUserDeets;
}, 10000);
};
}
angular
.module('app', [])
.controller('exampleController', exampleController)
.factory('exampleFactory', exampleFactory);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div class="container-fluid text-center" ng-app="app">
<div class="container text-center" ng-controller="exampleController">
<form name="userLoginForm" ng-submit="submit(userForm)" ng-model="userForm" novalidate>
<input type="email" name="email" ng-model="userForm.email" required="">
<input type="text" name="password" ng-model="userForm.text" required="">
<input type="submit" value="Submit" ng-disabled="userLoginForm.$invalid">
</form>
<pre>{{userForm}}</pre>
</div>
</div>

Submit form with ng-submit and trigger synchronous post request

I have a form that I want to trigger validation on when the user clicks submit. If the validation fails, then suitable error messages are displayed. This much works.
However if the validation passes I want the form to submit a synchronous POST request with full page reload as if the action and method parameters were set as usual.
How does one achieve trigger the normal post action (not AJAX) from the ng-submit function on the AngularJS scope?
My form of course looks basically like the following:
<form id="myForm" name="myForm" ng-submit="formAction(this, models)">
...
<input type="submit" value="Submit">
</form>
The best I can think of is to mirror the contents of the form with another hidden form submitting that one, but there must be a better way!
TO CLARIFY: If validation passes, I need the form submission to essentially behave like a normal synchronous post form submission which lands the user at the page returned by the server from the post request.
http://plnkr.co/edit/cgWaiQH8pjAT2IRObNJy?p=preview
Please check this plunkr
Basically what I am doing is passing the $event object. form is the target of the event object, and we can submit it.
function Ctrl($scope) {
$scope.list = [];
$scope.text = 'hello';
$scope.submit = function($event) {
if ($scope.text) {
$scope.list.push(this.text);
if(this.text === 'valid'){
$event.target.submit();
}
$scope.text = '';
}
};
}
Try inside formAction after you've submitted the data:
$route.reload();
I dont think you need to do a full page refresh. You have a single page app I am assuming; use it. Try something like this:
<section class="contact">
<article>
<h1>Contact</h1>
<form role="form" name="contactForm" ng-submit="formSubmit(contactForm)">
<div class="form-group">
<input class="form-control" ng-model="name" name="name" id="name" type="text" placeholder="Name" required/>
</div>
<div class="form-group">
<input class="form-control" ng-model="email" name="email" id="email" type="email" placeholder="Email Address" required/>
</div>
<div class="form-group">
<textarea class="form-control" ng-model="message" name="message" id="message" rows="5"></textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-lg">Send Message</button>
<a class="btn btn-default btn-lg" href='mailto:me#something.net'>Or email me</a>
</div>
</form>
</article>
'use strict';
MyApp.controller('ContactController', function ContactController ($scope, EmailService) {
$scope.formSubmit = function(form) {
EmailService.send(form).then(function(data) {
if(data.message.sent) {
$scope.resetForm();
alert("Message Sent");
}
else {
alert("Something went wrong. Try emailing me.");
}
});
}
$scope.resetForm = function() {
$scope.name = "";
$scope.email = "";
$scope.message = "";
}
});
MyApp.factory('AjaxService', function AjaxService ($q, $http) {
return {
http: function(ajaxParams) {
var deferred = $q.defer();
$http(ajaxParams)
.success(function (data, status, headers, config) {
deferred.resolve({
success: true,
status: status,
message: data
});
})
.error(function (data, status, headers, config) {
deferred.reject({
success: false,
status: status,
message: "Http Error"
});
});
return deferred.promise;
}
}
});
MyApp.factory('EmailService', function EmailService (AjaxService) {
return {
send: function(emailData) {
var ajaxParams = {
method: 'POST',
url: ''//where ever your form handler is,
data: {
name: emailData.name.$modelValue,
email: emailData.email.$modelValue,
message: emailData.message.$modelValue
},
cache: false
}
return AjaxService.http(ajaxParams);
}
}
});

Resources