Angular Material DatePicker and NG-CHANGE - angularjs

When a user selects a date on the md-datepicker component, I need to call the server to check the schedule for the selected date. The thing is, I can't get my function to fire using ng-change, which seems to be the only option on doing this. Any thoughts on why this is not working?
form.html
<div
layout-padding>
<form
name="form"
novalidate
ng-submit="form.$valid && save()">
<div
layout>
<md-input-container
class="md-block"
flex="100">
<label>Nome Completo</label>
<input
name="fullName"
ng-model="costumer.fullName"
required
disabled/>
<div
ng-messages="form.fullName.$error">
<div ng-message="required">O cliente não foi específicado</div>
</div>
</md-input-container>
</div>
<div
layout>
<md-input-container
flex>
<label>Data</label>
<md-datepicker
name="date"
ng-model="appointment.when"
md-open-on-focus
md-min-date="today">
</md-datepicker>
<div
ng-messages="form.date.$error">
<div ng-message="valid">Data inválida</div>
<div ng-message="mindate">Data anterior à atual</div>
</div>
</md-input-container>
<md-input-container
flex="50">
<label>Horário</label>
<md-select
name="whatTime"
ng-model="appointment.whatTime"
required>
<md-option value="0">08:00 - 09:00</md-option>
<md-option value="1">09:00 - 10:00</md-option>
<md-option value="2">10:00 - 11:00</md-option>
<md-option value="3">13:00 - 14:00</md-option>
<md-option value="4">14:00 - 15:00</md-option>
<md-option value="5">15:00 - 16:00</md-option>
<md-option value="6">16:00 - 17:00</md-option>
<md-option value="7">17:00 - 18:00</md-option>
</md-select>
<div
ng-messages="form.whatTime.$error">
<div
ng-message="required">Selecione um horário</div>
</div>
</md-input-container>
</div>
<md-button
type="submit">Confirmar</md-button>
</form>
</div>
controller.js
angular.module('Application').controller('NewAppointmentController',
['$scope', '$routeParams', 'CostumerService', 'AppointmentService',
function($scope, $routeParams, CostumerService, AppointmentService) {
console.log('NewAppointmentController init');
console.log('Costumer: ' + $routeParams.costumerId);
$scope.today = new Date();
$scope.appointment = {};
$scope.appointment.when = $scope.today;
$scope.save = save;
$scope.checkSchedule = checkSchedule;
CostumerService.getUniqueById($routeParams.costumerId)
.then(function(data){
$scope.costumer = data;
console.log('Costumer name: ' + data.fullName);
}, function(error){
console.log('Erro');
});
function save() {
console.log('Clicked');
$scope.appointment.costumer = $scope.costumer;
AppointmentService.save($scope.appointment)
.then(function(data) {
console.log('Saved');
}, function(error){
console.log('Error');
});
}
function checkSchedule() {
console.log('Changed: ');
}
}]);

It seems to work for me. See this CodePen, ngChange with Datepicker. I added
<md-datepicker
name="date"
ng-model="appointment.when"
ng-change="checkSchedule()"
md-open-on-focus
md-min-date="today">
</md-datepicker>
Everytime you change the date, it will be logged to the console. Although, it really seems like you should be using $asyncValidators as described in Custom Validation.

Related

Get all the values of form fields having same ng-model in angularjs

I am new in angularjs and making a dynamic form fields with ng-repeat and all my fields having the same ng-model
My Code:
<form name="dataset" class="md-inline-form" novalidate>
<div ng-repeat="column in columns">
<input type="hidden" name="column_name" ng-model="dataset.columnName" value="{{column}}">
<label for="">Column: <strong>{{column}}</strong></label>
<div layout="column" layout-gt-xs="row">
<md-input-container flex>
<label>Select Type</label>
<md-select name="type" ng-model="dataset.type" required>
<md-option value="string">String</md-option>
<md-option value="numeric">Numeric</md-option>
</md-select>
<div class="errors" ng-messages="dataset.state.$error">
<div ng-message="required">Required</div>
</div>
</md-input-container>
</div>
</div>
<md-button type="submit" ng-click="SavevalidateColumns()" class="md-raised md-accent" aria-label="Submit">Validate Now</md-button>
</form>
Now i just want to get the values of my all dynamically created fields in my controller. Can any one help me regarding this ?
You have to use my code.
<form name="dataset" class="md-inline-form" novalidate>
<div ng-repeat="column in columns">
<input type="hidden" name="column_name" ng-model="dataset.columnName" value="{{column}}">
<label for="">Column: <strong>{{column}}</strong></label>
<div layout="column" layout-gt-xs="row">
<md-input-container flex>
<label>Select Type</label>
<md-select name="type" ng-model="dataset.type" required>
<md-option value="string">String</md-option>
<md-option value="numeric">Numeric</md-option>
</md-select>
<div class="errors" ng-messages="dataset.state.$error">
<div ng-message="required">Required</div>
</div>
</md-input-container>
</div>
</div>
<md-button type="submit" ng-click="SavevalidateColumns(dataset)" class="md-raised md-accent" aria-label="Submit">Validate Now</md-button>
</form>
First You have to pass data in funciton.
Your controller code:
(function () {
'use strict';
angular.module('moduleName', [])
.controller('myCtrl',
function ($scope) {
$scope.SavevalidateColumns = function (dataset) {
var colName = dataset.columnName;
var type = dataset.type;
console.log(colName + "::::" + type);
};
});
})();
You have to inject this module into app also.

why scope variable is not accessible in angular components

I have written a angular directive to read the file input data. However the updated scope variable is not accessible when I click on update button. why I am unable to access the file variable that is updated in ngFileSelect directive?
JS
// Define the `changeWord` module
angular.module('changeWord', []);
/// <reference path="changeWord.component.js" />
angular.
module('changeWord').
component('changeWord', {
templateUrl: 'change-word/change-word.template.html',
controller: function ChangeWordController($scope, dictionaryService) {
var self = this;
//$rootScope.loggedIn = $cookies.get('loggedIn');
self.formShowing = false;
$scope.search = function () {
dictionaryService.getWordsStartWith(self.searchText, function (r) {
self.searchResults = r;
});
};
$scope.change = function (id) {
dictionaryService.getWord(id, result => {
self.key = id;
self.word = result.word;
self.wordInEnglish = result.wordInEnglish;
self.pronunciation = result.pronunciation;
var syns ='';
angular.forEach(result.synonyms, a =>{
syns += (syns == '') ? a.wordInEnglish : ', ' + a.wordInEnglish;
})
self.synonyms = syns;
syns = '';
angular.forEach(result.antonyms, a => {
syns += (syns == '') ? a.wordInEnglish : ', ' + a.wordInEnglish;
})
self.antonyms = syns;
});
}
$scope.clear = function () {
angular.element(document.querySelector('#pFile')).val(null);
self.word = '';
self.wordInEnglish = '';
self.pronunciation = '';
self.synonyms = '';
self.antonyms = '';
};
$scope.update = function () {
dictionaryService.deleteWord(self.key);
// unable to access the scope here
dictionaryService.addNewWord(self.word, self.wordInEnglish, self.pronunciation, $scope.file, self.synonyms, self.antonyms);
this.clear();
self.formShowing = false;
}
}
}).directive("ngFileSelect", function () {
return {
link: function ($scope, el) {
el.bind("change", function (e) {
$scope.file = (e.srcElement || e.target).files[0];
//$scope.update();
})
}
}
});
HTML
<div ng-cloak>
<form name="changeForm" button-form ng-submit="update()" ng-if="$ctrl.formShowing">
<md-card flex flex-gt-md="70">
<md-card-header>
<md-card-avatar>
<md-icon class="md-avatar-icon">edit</md-icon>
</md-card-avatar>
<md-card-header-text>
<span class="md-title">Change Existing Word</span>
<span class="md-subhead">in kannada dictionary</span>
</md-card-header-text>
</md-card-header>
<md-card-content>
<md-input-container class="md-block">
<input name="word" ng-model="$ctrl.word" placeholder="Word in Kannada" required />
<div ng-messages="changeForm.word.$error" ng-show="changeForm.word.$dirty" role="alert">
<div ng-message="required">This is required!</div>
</div>
</md-input-container>
<md-input-container class="md-block">
<input name="wordInEnglish" ng-model="$ctrl.wordInEnglish" placeholder="Word in English" disabled />
<div ng-messages="changeForm.wordInEnglish.$error" ng-show="changeForm.wordInEnglish.$dirty" role="alert">
<div ng-message="required">This is required!</div>
</div>
</md-input-container>
<p flex layout="row">
<md-input-container class="md-block" flex="50">
<input ng-model="$ctrl.pronunciation" placeholder="Pronunciation" />
</md-input-container>
<md-input-container class="md-block" flex="50">
<input id="pFile" type="file" ng-File-Select accept="audio/*" capture aria-label="Pronunciation Audio">
</md-input-container>
</p>
<md-input-container class="md-block">
<textarea ng-model="$ctrl.synonyms" placeholder="Synonyms"></textarea>
</md-input-container>
<md-input-container class="md-block">
<textarea ng-model="$ctrl.antonyms" placeholder="Antonyms"></textarea>
</md-input-container>
</md-card-content>
<md-card-actions>
<md-button class="md-raised md-primary" type="submit">Save</md-button>
<md-button class="md-accent" ng-click="$ctrl.formShowing = !$ctrl.formShowing">Cancel</md-button>
</md-card-actions>
</md-card>
</form>
<md-content class="md-padding">
<form name="searchForm" button-form ng-submit="search()">
<md-input-container md-no-float class="md-block">
<input name="searchText" ng-model="$ctrl.searchText" type="text" placeholder="Search">
<md-icon style="display:inline-block;" type="submit">search</md-icon>
<div class="hint" ng-show="searchForm.searchText.$dirty">Press Enter to search</div>
</md-input-container>
</form>
<md-list flex>
<md-list-item class="md-2-line" ng-repeat="result in $ctrl.searchResults" ng-click="null">
<div class="md-list-item-text" layout="column">
<h3>{{ result.wordInEnglish }}</h3>
<p>{{ result.word }}</p>
<md-button name="ch" class="md-raised md-primary md-secondary" ng-click="$ctrl.formShowing=!$ctrl.formShowing; change(result.$id);">Change</md-button>
</div>
</md-list-item>
</md-list>
</md-content>
</div>
Perfect, $scope is not existing in component. Need to use keyword this

How to get back data from DB after sent it from client side?

I have profile page in angular js, after I filled and sent them to DB. Then once again if I come back to the same profile page I didn't get any values in the field.
profile.html
<form name="profileForm">
<br/>
<div flex style="max-width:700px;">
<md-input-container class="md-block">
<label>Name</label>
<input ng-model="vm.name"></input>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block">
<label>Mobile Number</label>
<input ng-model="vm.mobile"></input>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block">
<label>Email</label>
<input ng-model="vm.email"></input>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<label>DOB:</label>
<md-datepicker ng-model="vm.profileForm.dob" md-placeholder="Enter date">
</md-datepicker>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block" >
<label>Country</label>
<md-select ng-model="vm.profileForm.Country" ng-change="vm.getCountryStates()">
<md-option ng-repeat="countryName in vm.countries" value="{{countryName.id}}" >
{{countryName.country}}
</md-option>
</md-select>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block" >
<label>State</label>
<md-select ng-model="vm.profileForm.State" ng-change = "vm.getStateCities()">
<md-option ng-repeat="stateName in vm.states" value="{{stateName.Id}}">
{{stateName.state}}
</md-option>
</md-select>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block" >
<label>City</label>
<md-select ng-model="vm.profileForm.City">
<md-option ng-repeat="cityName in vm.cities" value="{{cityName.Id}}">
{{cityName.city}}
</md-option>
</md-select>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block" >
<label>Postal Code</label>
<input name="postalCode" ng-model="vm.profileForm.postalCode" ng-pattern="/^[0-9]{6}$/" md-maxlength="6">
</md-input-container>
</div>
<span style="color:green; font-size:20px;">{{vm.message}}</span>
<div layout="row" layout-align="space-between center">
<div>
<img src="assets/icons/fonts/backArrow.png" alt="image caption" style="width:18px; height:18px">
<a ng-href ng-click="vm.nextTab()" >Back</a>
</div>
<div style="margin-right:300px">
<a ng-href="http://localhost:3000/pages/dashboard">Skip</a>
<md-button class="md-raised md-primary" ng-click="vm.profileInfo(vm.profileForm);">Save & Continue</md-button>
</div>
</div>
</form>
In the picture first 3 values getting through ngStorage, after filled remaining fields data stored in DB. For chekcBox I have used cascading dropdown.
profile.js
(function ()
{
'use strict';
angular
.module('app.invite-friends')
.controller('InviteFriendsController', InviteFriendsController);
/** #ngInject */
function InviteFriendsController(Friendslist, $localStorage, $scope, $http, $location, CustomerService)
{
var vm = this;
vm.countries = CustomerService.getCountry();
vm.getCountryStates = function(){
vm.states = CustomerService.getCountryState(vm.profileForm.Country);
vm.cities =[];
}
vm.getStateCities = function(){
vm.cities = CustomerService.getStateCity(vm.profileForm.State);
}
vm.uid = $localStorage._id;
vm.profileInfo = function(userData){
$http({
url:'http://192.168.2.8:7200/api/profile_save',
method:'POST',
data: {info:userData, loginId:vm.uid}
}).then(function(res){
if(res.data.success){
vm.message = 'Your profile information has been saved successfully.';
$location.path('/pages/dashboard')
}
}, function(error){
alert(error.data);
});
};
$http({
url:'http://192.168.2.8:7200/api/checkIfExists',
method:'POST',
data: {userId: vm.uid}
}).success(function(res){
vm.name = res.result[0].name;
vm.mobile = res.result[0].mobile;
vm.email = res.result[0].email;
vm.DOB = res.result[0].DOB;
vm.Country = res.result[0].Country;
vm.State = res.result[0].State;
vm.City = res.result[0].City;
vm.postalCode = res.result[0].PostCode;
}, function(error){
alert(error.data);
});
}
})();
All you ng-model is getting or updating data to vm.profileForm in the view where as while you setting data to view form controller you are adding properties to vm, not to vm.profileForm
Change the following code in $http success
from
vm.DOB = res.result[0].DOB;
vm.Country = res.result[0].Country;
vm.State = res.result[0].State;
vm.City = res.result[0].City;
vm.postalCode = res.result[0].PostCode;
to
vm.profileForm.dob = res.result[0].DOB;
vm.profileForm.Country = res.result[0].Country;
vm.profileForm.State = res.result[0].State;
vm.profileForm.City = res.result[0].City;
vm.profileForm.postalCode = res.result[0].PostCode;

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

Why using directive I loose the Material effects?

I'm trying to understand what exactly is happening.
I had a form with Angular Material, something like:
<div layout-gt-sm="row">
<md-input-container class="md-block" flex-gt-sm>
<label>First name</label>
<input ng-model="user.firstName">
</md-input-container>
<md-input-container class="md-block" flex-gt-sm>
<label>Last Name</label>
<input ng-model="theMax">
</md-input-container>
</div>
... with the onfocus and onblur effecs + inputs layout full.
After that working, I change the form to work with directives and the form start to be like:
<div layout-gt-sm="row" class="core no-padding-bottom">
<!-- effect working -->
<md-input-container class="md-block" flex-gt-sm>
<md-icon><i class="material-icons">email</i></md-icon>
<input type="text" name="asd" placeholder="asd">
</md-input-container>
<!-- effect not working -->
<input-test name="name"></input-test>
</div>
... directive template:
<md-input-container class="md-icon-float md-block" flex-gt-sm md-no-float>
<md-icon class="material-icons">
<i class="material-icons">{{ attrs.icon }}</i>
</md-icon>
<input
type="text"
name="{{ attrs.name }}">
<div ng-messages="form[attrs.name].$error" role="alert">
<div ng-message="server">{{ form[attrs.name].$error.serverMessage }}</div>
</div>
</md-input-container>
... the directive:
app.directive('inputTest', function($injector, $q, $location) {
return {
replace: true,
restrict: 'AE',
scope: {
model: '=',
form: '='
},
templateUrl: baseViewPath('directives/form/text.html'),
link: function($scope, $element, $attrs) {
$scope.attrs = $attrs;
$scope.mask = function() {
if(typeof $attrs.mask !== 'undefined') {
return $attrs.mask;
}
};
}
};
});
Now, the form is working 50%, where is been send and validate as well but there's no Material effects and no full fields on screen.
What could that be?
UPDATE
I think that I "fixed" changing the placeholder to label
<label>{{ attrs.placeholder }}</label>

Resources