Why using directive I loose the Material effects? - angularjs

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>

Related

md dialog not working properly?

I'm new to angular material:
I want to show dialog for editing records in a table:
I referenced angular material and angular aria, used ngMaterial dependency and $mdDialog service.
I have a div containing all editing fields, the div visibility is set to hidden:
<div style="visibility: hidden">
<div class="md-dialog-container" id="taskEdit">
<md-dialog style="width:100%; height:100%" layout-padding>
<md-toolbar>
<div class="md-toolbar-tools">
<h2>Edit Task</h2>
<span flex></span>
</div>
</md-toolbar>
<ng-form name="TaskForm">
<div layout-gt-sm="row">
<md-input-container>
<label>Task Title</label>
<input name="TaskTitle" ng-model="task.title" required>
<div ng-messages="TaskForm.TaskTitle.$error">
<div ng-message="required">This is required</div>
</div>
</md-input-container>
<md-input-container class="md-block" flex-gt-sm>
<label>Description</label>
<textarea ng-model="task.description" md-maxlength="150" md-select-on-focus></textarea>
</md-input-container>
<md-input-container class="md-block">
<label>Due Date</label>
<md-datepicker style="margin-top: 2px;" ng-model="task.dueDate"></md-datepicker>
</md-input-container>
<md-input-container>
<label>Task Status</label>
<input name="TaskStatus" ng-model="task.status">
</md-input-container>
</div>
</ng-form>
<input class="btn btn-primary" style="width:15%" type="submit" ng-disabled="!TaskForm.$valid" ng-click="EditTask()" value="Submit" aria-label="submit" />
</md-dialog>
</div>
</div>
here's the showDialog function::
$scope.showDialog = function () {
$mdDialog.show({
controller: DialogController,
contentElement: '#taskEdit',
parent: angular.element(document.body),
clickOutsideToClose: true
});
};
function DialogController($scope, $mdDialog) {
$scope.hide = function () {
$mdDialog.hide();
};
$scope.cancel = function () {
$mdDialog.cancel();
};
}
but when I click the button, the dialog is not appearing properly, it lacks the animation and is rendered in the same layer as the parent page:
You need to refer the angular material css
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.4/angular-material.css">

Angular Material DatePicker and NG-CHANGE

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.

Angularjs ngMessage not showing

I created a directive to compare password and confirm password fields and show error message if it won't match.
(function () {
'use strict';
var compareTo = function () {
return {
require: "ngModel",
scope: {
otherModelValue: "=compareTo"
},
link: function (scope, element, attributes, ngModel) {
ngModel.$validators.compareTo = function (modelValue) {
return modelValue == scope.otherModelValue;
};
scope.$watch("otherModelValue", function () {
ngModel.$validate();
});
}
};
};
angular.module('StarterApp').directive("compareTo", compareTo);
})();
My HTML:
<form name="updatePwdForm" novalidate>
<md-input-container class="md-block">
<label for="password">Password:</label>
<input type="password" name="password" ng-model="ctrl.updatepassword.password" />
</md-input-container>
<md-input-container class="md-block">
<label for="confirmPassword">Confirm Password:</label>
<input type="password" name="confirmPassword" label="confirmPassword" ng-model="ctrl.updatepassword.confirmpassword" required
compare-to="ctrl.updatepassword.password" />
<div ng-messages="updatePwdForm.confirmPassword.$error" style="color:maroon" role="alert">
<div ng-message="required">Password and Confirm Password are not same!</div>
</div>
</md-input-container>
<md-button class="md-raised md-primary" ng-disabled="updatePwdForm.$invalid" ng-click="ctrl.updatePassword()">Update</md-button>
</form>
</md-content>
I am sure that my directive is comparing values and returning false if it won't match because my button is in disable mode still i type correct confirmpassword, but it's not showing my ngMessage.
am i missing something?
Thanks in advance.
Instead of
<div ng-message="required">
you should have
<div ng-message="compareTo">
Since the name of your validator is compareTo.

get ng-model $resource in controller

I need to set the ng-model via controller by selecting one of the listed images in Dialog and insert the ng-model of the form to record it in json-server.
My resource is provide by json-server.
Is there any way to do this? Or there's no way .. or some other way?
Template:
<form class="form-horizontal" role="form" ng-submit="addItem($stateParams.section)" enctype="multipart/form-data">
<div layout="row" layout-wrap>
<div flex="75">
<md-card>
<md-card-content>
<h2>Adicionar novo Post</h2>
<md-input-container>
<label>Digite o título aqui</label>
<input ng-model="item.title">
</md-input-container>
<md-input-container>
<label>Introdução</label>
<input ng-model="item.subtitle">
</md-input-container>
<md-input-container>
<label>Link permanente</label>
<input ng-model="item.slug">
</md-input-container>
<text-angular ng-model="item.content"></text-angular>
<md-input-container>
<label>Resumo</label>
<input ng-model="item.excerpt">
</md-input-container>
</md-card-content>
</md-card>
</div>
<div flex="25">
<md-card>
<md-card-content>
<h2>Configurações do Post</h2>
<md-input-container ng-controller="PublishedControl">
<md-select name="situation" ng-model="item.situation" placeholder="Status do Post">
<md-option ng-repeat="pub in publisheds" ng-value="{{pub.id}}">{{pub.name}}</md-option>
</md-select>
</md-input-container>
<div layout layout-sm="column">
<md-input-container flex>
<label>Date</label>
<input type="date" ng-model="item.posted">
</md-input-container>
<md-input-container flex>
<label>Time</label>
<input type="time" ng-model="item.posted">
</md-input-container>
</div>
<md-card-footer layout="row" layout-sm="column" layout-align="center center" layout-wrap>
<md-button class="md-raised md-primary" type="submit">Salvar</md-button>
<md-button class="md-raised" ui-sref="listItems({section: $stateParams.section})">Cancelar</md-button>
</md-card-footer>
</md-card-content>
</md-card>
<md-card ng-if="categorias[0].cats">
<md-card-content>
<h2>Categorias</h2>
<div layout-padding>
<!-- <checkbox ng-repeat="cat in categorias[0].cats" value="{{cat.id}}" ng-checked="{{item.cats.indexOf(cat.id) > -1}}" ng-model="item.cats">{{cat.name}}</md-checkbox> -->
<label ng-repeat="cat in categorias[0].cats" style="display:block;" layout="row" flex="100">
<input type="checkbox" checklist-model="item.cats" checklist-value="cat.id"> {{cat.name}}
</label>
</div>
</md-card-content>
</md-card>
<md-card>
<md-card-content ng-controller="MediaController">
<h2>Imagem em Destaque</h2>
<div class="input-group form-group">
<figure ng-if="item.image"><img ng-model="item.image" ng-src="item.image" alt=""></figure>
<md-button class="md-raised" type="button" ng-click="chooseMedia($event)">Escolha uma Imagem</md-button>
</div>
</md-card-content>
</md-card>
</div>
</div>
</form>
Controller:
module.controller('MediaController', ['$scope', '$mdDialog', 'Media', function($scope, $mdDialog, Media) {
$scope.chooseMedia = function(ev){
$mdDialog.show({
parent : angular.element(document.body),
controller : chooseMediaControl,
ariaLabel : 'Choose Media',
targetEvent : ev,
clickOutsideToClose : true,
templateUrl : 'partials/tpl/media.html'
})
function chooseMediaControl($scope, $mdDialog, Media) {
$scope.media = Media.query();
$scope.cancelMedia = function() {
$mdDialog.cancel();
};
$scope.applyMedia = function() {
$scope.item.image = $scope.image;
$mDialog.hide();
};
$scope.inserMedia = function(imageurl){
$scope.image = imageurl;
};
}
}
}])
Service:
.factory('Media',function($resource){
return $resource('http://localhost:5000/media/:id',{id:'#id'},{
update: {
method: 'PUT'
}
});
})

Angular directive for custom validation

I'm trying to create the AngularJS directive, which should vilidate the form. The form has two inputs. The valid case is when the imputs are either both empty or both filled with any string value.
<form name="recipientsForm" novalidate>
<md-input-container>
<label>Name</label>
<input name="name" type="text" ng-model="relationship.name">
</md-input-container>
<md-input-container>
<md-select name="type" placeholder="Select your relation... " ng-model="relationship.relationshipType">
<md-option ng-repeat="type in relationshipTypes" value="{{type.relationshipType}}">
{{type.name}}
</md-option>
</md-select>
</md-input-container>
</form>
The divective should be generic for other forms with such kind of validation.
My approach seems not working:
.html:
<form name="recipientsForm" novalidate>
<md-input-container>
<label>Name</label>
<input name="name" type="text" ng-model="relationship.name" value="" empty-or-both-filled="relationship.relationshipType">
<div ng-messages="recipientsForm.name.$error">
<div ng-message="emptyOrBothFilled">Enter name.</div>
</div>
</md-input-container>
<md-input-container>
<md-select name="type" placeholder="Select your relation... " ng-model="relationship.relationshipType" empty-or-both-filled="relationship.name">
<md-option ng-repeat="type in relationshipTypes" value="{{type.relationshipType}}">
{{type.name}}
</md-option>
</md-select>
<div ng-messages="recipientsForm.type.$error">
<div ng-message="emptyOrBothFilled">Pick relationship.</div>
</div>
</md-input-container>
</form>
.js file:
(function () {
'use strict';
angular
.module('app')
.directive('emptyOrBothFilled', [emptyOrBothFilled]);
function emptyOrBothFilled() {
return {
restrict: 'A',
require: 'ngModel',
scope: {
targetNgModel: '=emptyOrBothFilled'
},
link: function($scope, element, attrs, ngModel) {
ngModel.$validators.emptyOrBothFilled = function(val) {
console.log($scope.targetNgModel);
return (!val && !$scope.targetNgModel) || (!!val && !!$scope.targetNgModel);
}
$scope.$watch('targetNgModel', function() {
ngModel.$validate();
})
}
}
}
})();
An alternativ approach just using ng-disabled and ng-required:
<form name="recipientsForm" novalidate>
<md-input-container>
<label>Name</label>
<input name="name" type="text" ng-model="relationship.name">
<div ng-messages="recipientsForm.name.$error">
<div ng-message="emptyOrBothFilled">Enter name.</div>
</div>
</md-input-container>
<md-input-container>
<md-select name="type" placeholder="Select your relation... " ng-model="relationship.relationshipType" ng-disabled="relationship.name" ng-required="relationship.name">
<md-option ng-repeat="type in relationshipTypes" value="{{type.relationshipType}}">
{{type.name}}
</md-option>
</md-select>
</md-input-container>
</form>

Resources