I just combined my scopes for models using this method: How can I combine multiple scope models in Angular?
but now it's creating a separate field object outside of the fields object which it didn't do before.
HTML
<li order="" class="field-dropped text" ng-repeat="field in theForm.fields" ng-switch="theForm.field.type">
<div class="field-actions"><i class="icon-edit"></i> <i class="icon-move"></i> <i class="icon-remove"></i>
</div>
<h4>{{theForm.field.label}}</h4>
<em class="field-desc">{{theForm.field.desc}}</em>
<!-- type: text -->
<input ng-switch-when="text" type="text" placeholder="" disabled class="span6">
<!-- type: para -->
<textarea ng-switch-when="para" type="text" placeholder="" disabled class="span6"></textarea>
<!-- type: drop -->
<select ng-switch-when="drop" placeholder="" disabled class="span6"></select>
<div class="field-options well">
<label>Field Title</label>
<input type="text" placeholder="Field Label" class="span8" ng-model="theForm.field.label">
<label>Field Description</label>
<textarea class="description span8" type="text" placeholder="Field Description" ng-model="theForm.field.desc"></textarea>
<label class="checkbox">
<input type="checkbox" value="" ng-model="theForm.field.req">Required?</label>
<!-- type: drop -->
<label ng-switch-when="drop" class="checkbox">
<input type="checkbox" value="" ng-model="theForm.field.dropOptionsMul">Allow Multiple Choices?</label>
<label ng-switch-when="drop">Options</label>
<em ng-switch-when="drop">Enter a new option on each line.</em>
<textarea ng-switch-when="drop" class="span6" type="text" placeholder="Options" ng-list="
" ng-trim="false" ng-model="theForm.field.dropOptions"></textarea>
</div>
<input class="sortOrder" id="" name="" value="" type="hidden">
</li>
JS
angular.module('formApp', [])
.controller('formController', ['$scope', function($scope) {
$scope.theForm = {
formTitle: '',
formDesc: '',
fields: []
};
$scope.addField = function(ui) {
var type = ui.draggable.attr("id");
console.log(type);
$scope.theForm.fields.push({type: type, label:'Added Form Title', desc:'Added Form Desc', req:false});
console.log("for-break");
};
}])
.directive('drag', function() {
return {
restrict: "A",
link: function(scope, elem, attrs) {
$( elem ).draggable({
helper: "clone",
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
drop: function( event, ui ) {
}
});
}
}
})
.directive('drop', function() {
return {
restrict: "A",
link: function(scope, elem, attrs) {
$( elem ).droppable({
hoverClass: "holder-state-highlight",
drop: function(event, ui) {
//handleDropEvent(event, ui);
//sortOrder();
scope.$apply(function(){
angular.element('#theForm').scope().addField(ui);
});
}
});
}
}
});
JSON Output
{
"formTitle": "",
"formDesc": "",
"fields": [],
"field": {
"label": "The actual field title",
"desc": "The actual field description"
}
}
ng-repeat="field in theForm.fields"
field becomes the 'shortcut' for each object in theForm.fields.
So inside ng-repeat you call it just by type.
It's like saying
for (i = 0; i < theForm.fields.length; i++) {
var field = theForm.fields[0];
// from now on you access it by field
field.type = 'My Type';
}
Related
I have a set of radio buttons inside a directive. The directive has an ng-repeat, so it exists multiple times.
I'm able to populate the input fields of the directive, but the radio buttons won't react.
angular.module('account-form-client-de', [])
.controller('ctrl', function($scope) {
$scope.owners = [];
$scope.addOwner = function() {
$scope.owners.push({
class: 'person',
name: 'new owner',
percentage: 0
});
}
$scope.addOwner();
$scope.addOwner();
})
.directive("newOwner", function() {
var options = {
restrict: 'E',
replace: true,
scope: {
owner: '=',
remove: '&'
},
link: function(scope, element, attrs, controller, $parent) {
},
template: `
<div class="table-owners item-row">
<div class="checkbox">
<input type="radio" name="type" ng-model="owner.class" value="person" validate-on-change>
<label for="person" translate>
table_owners.person
</label>
</div>
<div class="checkbox">
<input type="radio" name="type" ng-model="owner.class" value="company" validate-on-change>
<label for="company" translate>
table_owners.company
</label>
</div>
<input name="owners_name" ng-model="owner.name" type="text" placeholder="" class="form-control input-md">
<input name="owners_percentage" ng-model="owner.percentage" type="number" placeholder="" class="form-control input-md">
</div>`
};
return options;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="account-form-client-de" ng-controller="ctrl">
<pre>{{owners}}</pre>
<new-owner ng-repeat="owner in owners track by $index" owner="owner"></new-owner>
<button ng-click="addOwner()">add owner</button>
</div>
Since both the inputs and radio buttons refer to a property in the owner object, I fail to see why the inputs bind, and the radio buttons won't even become checked.
Any ideas?
It's because when you have the same directive multiple times, you have the same radio buttons with the same values multiple times. Then, the HTML parser gets confused. I fixed it by wrapping each row in a <form> (which you don't have to submit), so it's valid again.
angular.module('account-form-client-de', [])
.controller('ctrl', function($scope) {
$scope.owners = [];
$scope.addOwner = function() {
$scope.owners.push({
class: 'person',
name: 'new owner',
percentage: 0
});
}
// Add two owners to begin with
$scope.addOwner();
$scope.addOwner();
})
.directive("newOwner", function() {
var options = {
restrict: 'E',
replace: true,
scope: {
owner: '=',
remove: '&'
},
link: function(scope, element, attrs, controller, $parent) {
},
template: `
<form class="table-owners item-row">
<div class="checkbox">
{{owner.class}}
<input type="radio" name="person" value="person" ng-model="owner.class">
<label for="person" translate>
table_owners.person
</label>
</div>
<div class="checkbox">
<input type="radio" name="company" value="company" ng-model="owner.class">
<label for="company" translate>
table_owners.company
</label>
</div>
<input name="owners_name" ng-model="owner.name" type="text" placeholder="" class="form-control input-md">
<input name="owners_percentage" ng-model="owner.percentage" type="number" placeholder="" class="form-control input-md">
</form>`
};
return options;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="account-form-client-de" ng-controller="ctrl">
<pre>{{owners}}</pre>
<new-owner ng-repeat="owner in owners track by $index" owner="owner"></new-owner>
<button ng-click="addOwner()">add owner</button>
</div>
I am working on the project that needs to be updates with some functions. One is where i need to update EAV registration form and make choose option, where i have 2 radio buttons and text field. When I click on one of the radio buttons, it takes the value and places it in the input textbox. The problems starts when i try to save registration. This text field attributes are saved in database where one of them is "isRequired". I can't save form because textfield asks to type something in it, but there is already a value. When I disable "isRequired" it saves the form, but there is no value saved in database. When I type any symbol next to radio button value required field disappears and then I can save the value in database. That's why my question is why field can't catch the value. I will put some of the code in this question because I can't make test environment. Have only files on the server. Hope someone can answer or give some clues what to do. I have opinions that this problem might be cause by keypress events, angularjs, jquery or EAV model.
Image: https://postimg.org/image/j8mgjia1d/
Creating fields:
backendComponents.directive('eavFormatted', function($compile)
{
return {
restrict: "E",
scope: true,
replace: true,
transclude: true,
template: '<div class="form-group field_eav field_eav_{{ config.ID }} field_eav_{{ config.handle }}"><label class="control-label">{{ config.name }}</label><div ng-transclude></div></div>',
link: function(scope, element, attrs)
{
var config = JSON.parse(attrs.config);
scope.config = config;
delete attrs.config;
element.removeAttr('ng-transclude');
}
}
});
backendComponents.directive('eavField', function($compile, $timeout) {
return {
restrict: "E",
scope: true,
replace: true,
link: function(scope, element, attrs)
if (html) {
var fieldName = 'eav_' + config.ID;
if (config.isRequired) {
html = html + '<div class="text-danger" ng-show="isSubmitted && eavform.' + fieldName + '.$error.required">Lūdzu aizpildiet šo lauku</div>';
}
html = '<div><ng-form name="eavform">' + html + element.html() + '</ng-form></div>';
var newElem = angular.element(html);
var attrElem = input ? newElem.find(input) : newElem;
attrElem.attr('ng-model', 'vals.eav.' + config.ID);
attrElem.addClass('form-control');
attrElem.attr('placeholder', config.description);
attrElem.attr('name', fieldName);
if (config.isRequired) {
attrElem.attr('ng-required', true);
}
}
}
}
Fields from inspect element from browser:
<div class="form-group field_eav field_eav_2 field_eav_epasts" config="{"ID":2,"eavFieldGroupID":null,"classID":2,"stringIdentifier":null,"name":"E-pasts","description":"E-PASTS *","type":3,"dataType":1,"position":1,"handle":"epasts","isMultiValue":null,"isRequired":1,"isDisplayed":null,"isDisplayedInList":null,"valuePrefix":null,"valueSuffix":null,"valueFieldID":null,"fieldName":"specField_2"}">
<label class="control-label ng-binding">E-pasts</label>
<div ng-transclude="">
<div class="ng-scope">
<ng-form name="eavform" class="ng-pristine ng-invalid ng-invalid-required">
<input type="text" ng-model="vals.eav.2" class="form-control ng-pristine ng-invalid ng-invalid-required" placeholder="E-PASTS *" name="eav_2" ng-required="true" required="required">
<div class="text-danger ng-hide" ng-show="isSubmitted && eavform.eav_2.$error.required">Lūdzu aizpildiet šo lauku</div>
</ng-form>
</div>
</div>
</div>
<div ng-transclude="">
<div class="ng-scope">
<ng-form name="eavform" class="ng-pristine ng-invalid ng-invalid-required">
<input type="text" ng-model="vals.eav.2" class="form-control ng-pristine ng-invalid ng-invalid-required" placeholder="E-PASTS *" name="eav_2" ng-required="true" required="required">
<div class="text-danger ng-hide" ng-show="isSubmitted && eavform.eav_2.$error.required">Lūdzu aizpildiet šo lauku</div>
</ng-form>
</div>
</div>
Code from the file
<eav-formatted config="[[ eavFieldsHandle.epasts.toJson() ]]">
<eav-field></eav-field>
</eav-formatted>
<legend style="padding-top: 0px;">Izvēlieties piegādes veidu: </legend>
<input type="radio" class="input" name="radio-1" id="radio-1" value="Option1">
<span><b>Choose 1</span>
<input type="radio" class="input" name="radio-1" id="radio-2" value="Option2">
<span><b>Choose 2</span>
Script of the file
$( function() {
$('input[name="radio-1"]').on('change', function() {
$('input[name="eav_2"]').val($(this).val());
});
} );
I would like to dynamically display Person and Address data using label and input value in Summary Section. As the user edits the form fields, a list items with label + value should display in the summary tables. If value has been removed in the form, that associated label and value should be removed from the Summary Section.
I have added client side validation for each input element. I tried to solve this and couldn't figure out what is best way to do it. Any help would be appreciated.
Example:
// the main (app) module
var myApp = angular.module("myApp", []);
// add a controller
myApp.controller("myCtrl", function($scope) {
$scope.vm = {
caller: {
person: {
firstName: '',
lastName: '',
phoneOne: '',
email: ''
},
address: {
lineOne: '',
lineTwo: ''
}
}
};
$scope.save = function() {
console.log($scope.vm);
}
});
// add a directive
myApp.directive('showErrors', function($timeout, $compile) {
return {
restrict: 'A',
require: '^form',
link: function(scope, el, attrs, formCtrl) {
// find the text box element, which has the 'name' attribute
var inputEl = el[0].querySelector("[name]");
// convert the native text box element to an angular element
var inputNgEl = angular.element(inputEl);
// get the name on the text box
var inputName = inputNgEl.attr('name');
// only apply the has-error class after the user leaves the text box
var blurred = false;
inputNgEl.bind('blur', function() {
blurred = true;
el.toggleClass('has-error', formCtrl[inputName].$invalid);
});
scope.$watch(function(scope) {
return formCtrl[inputName].$invalid;
}, function(invalid, scope) {
// we only want to toggle the has-error class after the blur
// event or if the control becomes valid
if (!blurred && invalid) {
return
}
el.toggleClass('has-error', invalid);
});
scope.$on('show-errors-check-validity', function() {
el.toggleClass('has-error', formCtrl[inputName].$invalid);
});
scope.$on('show-errors-reset', function() {
$timeout(function() {
el.removeClass('has-error');
}, 0, false);
});
}
}
});
.form-group .help-block {
display: none;
}
.form-group.has-error .help-block {
display: inline;
}
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<form name="claimForm" ng-submit="save()">
<h3>PERSON</h3>
<div class="col-md-6">
<div class="form-group form-caller" show-errors>
<label class="control-label">First Name<span class="help-block" ng-if="claimForm.callerFirstName.$error.required"><i>[required]</i></span>
</label>
<input type="text" name="callerFirstName" ng-model="vm.caller.person.firstName" class="form-control" required="" />
</div>
</div>
<div class="col-md-6">
<div class="form-group form-caller" show-errors>
<label class="control-label">Last Name<span class="help-block" ng-if="claimForm.callerLastName.$error.required"><i>[required]</i></span>
</label>
<input type="text" name="callerLastName" ng-model="vm.caller.person.lastName" class="form-control" required="" />
</div>
</div>
<hr />
<h3>ADDRESS</h3>
<div class="col-md-6">
<div class="form-group" show-errors>
<label class="control-label">Address Line 1<span class="help-block" ng-if="claimForm.addressOne.$error.required"><i>[required]</i></span>
</label>
<input type="text" name="addressOne" ng-model="vm.caller.address.lineOne" class="form-control" required="" />
</div>
</div>
<div class="col-md-6">
<div class="form-group" show-errors>
<label class="control-label">Address Line 2<span class="help-block" ng-if="claimForm.addressTwo.$error.required"><i>[required]</i></span>
</label>
<input type="text" name="addressTwo" ng-model="vm.caller.address.lineTwo" class="form-control" required="" />
</div>
</div>
<hr />
<input type="submit" id="submit" value="SUBMIT" class="btn btn-primary btn-lg" />
{{vm | json }}
</form>
<h2>Summary</h2>
<div id="person">
<h3>PERSON </h3>
</div>
<hr />
<div id="address">
<h3>ADDRESS</h3>
</div>
</body>
Thanks in Advance
I have a problem with my ui-grid setup.
There is one ui-grid with an expandable row template loading a html file containing another ui-grid.
In this "subgrid" there is another expandable row template with another html-file containing 3 divs and a third ui-grid.
It works fine and shows all data needed.
In the most inner (is that a word?) expandable row (that with the 3 divs and the third grid) I want to use some functions to show and hide data with ng-show and some crud actions to edit the content of the third ("subsubgrid") ui-grid.
Since functions in the scope are not directly accessible I added an appScopeProvider and put the function in the subGridScope.
Now the function is accessed (I checked it with an alert).
In the function I set some boolean variables (e.g. $scope.showcreate = true), the divs contain ng-show directives (ng-show="showcreate") to hide or show the content of the div.
I debugged the function in the subGridScope and it sets the right values in $scope.showxyz, but the div is not hidden when set to false.
Do I need to re-render the page to "see" the change?
Do I need to change the ng-show directive?
Is there any good tutorial explaining this problem?
How would I access the "CRUD" actions? Would grid.appScope.function work even if the scope is kinda "stacked"?
If you need any more information, just ask, I will provide you with all information needed.
Here is the code:
app.js:
var alarmwesen = angular.module('alarmwesen', ['ui.grid', 'ui.grid.expandable']);
alarmwesen.controller('AlarmwesenCtrl', [
'$scope', '$http', '$log', '$templateCache', 'i18nService', '$interval', 'uiGridConstants', function ($scope, $http, $log, $templateCache, i18NService, $interval, uiGridConstants) {
$http.get('/api/action1)
.success(function (data) {
$scope.Beauftragter = data;
});
$scope.gridOptions = {
enableScrollbars : false,
expandableRowTemplate: 'expandableRowTemplate.html',
expandableRowHeight: 1400,
rowHeight: 36,
expandableRowScope: { subGridVariable: 'subGridScopeVariable' },
enableFiltering: true,
treeRowHeaderAlwaysVisible: false,
columnDefs: [
{ name: 'Trigraph',field:'ZeigeTrigraphen', width: '10%' },
{ name: 'Titel', field: 'Titel' },
],
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
gridApi.expandable.on.rowExpandedStateChanged($scope, function(row) {
if (row.isExpanded) {
row.entity.subGridOptions = {
appScopeProvider: $scope.subGridScope,
enableScrollbars: false,
expandableRowTemplate: 'expandableRowTemplate2.html',
expandableRowHeight: 700,
enableFiltering: false,
expandableRowScope: { subGridVariable: 'subsubGridScopeVariable' },
columnDefs: [
{ name: 'LfdAngabe', field:'LfdAngabe', width: '10%' },
{ name: 'Text', field: 'Text' }],
onRegisterApi:function(gridapi) {
this.subgridApi = gridapi;
gridapi.expandable.on.rowExpandedStateChanged($scope, function(row) {
if (row.isExpanded) {
row.entity.subsubGridOptions = {
appScopeProvider: $scope.subGridScope,
columnDefs: [
{ name: 'Durchführungsverantwortliche',width:'25%' }, { name: 'Auftrag' },
{ name: 'Aktionen', field: 'EinzelauftragId', width: '10%', cellTemplate: '<a id="Details" ng-click = "grid.appScope.BearbeiteAuftrag(row.entity.EinzelauftragId)" class="btn btn-success" )"><i class="glyphicon glyphicon-edit"</a><a id="Details" ng-click = "grid.appScope.LoescheAuftrag(row.entity.AuftragId)" class="btn btn-danger" )"><i class="glyphicon glyphicon-remove"</a>' }
]
};
$http.get('/api/action2')
.success(function(data) {
row.entity.subsubGridOptions.data = data;
});
}
});
}
};
$http.get('/api/action3?trigraph=' + row.entity.ZeigeTrigraphen)
.success(function(data) {
row.entity.subGridOptions.data = data;
});
}
});
}
};
$scope.subGridScope = {
NeuerAuftrag: function () {
$scope.showcreate = true;
$scope.showedit = false;
$scope.showdelete = false;
alert("Geht doch!");
}
};
$http.get('/api/AlarmwesenWebAPI/HoleAlle').then(function (resp) {
$scope.gridOptions.data = resp.data;
$log.info(resp);
});
}]);
html-files
<button class="btn btn-success" ng-click="grid.appScope.NeuerAuftrag()"><i class="glyphicon glyphicon-plus"></i>   Neuen Auftrag erstellen</button>
<div class="well" ng-show="showcreate">
<div class="well-header">Einzelauftrag erstellen</div>
<form role="form" ng-submit="ErstelleEinzelauftrag()" ng-model="Einzelauftrag" name="einzelauftragcreate" id="einzelauftragcreate">
<fieldset>
<input type="text" id="createEinzelauftragsId" class="" ng-model="Einzelauftrag.EinzelauftragsId" />
<input type="text" id="createAlarmkalenderId" class="" ng-model="Einzelauftrag.AlarmkalenderId" />
<input type="text" id="createAlarmmassnahmeTrigraph" class="" ng-model="Einzelauftrag.AlarmmassnahmeTrigraph" />
<input type="text" id="createEinzelmassnahmeLfdAngabe" class="" ng-model="Einzelauftrag.EinzelmassnahmeLfdAngabe" />
<div class="form-group">
<label for="createBeauftragterId">Durchführungsverantwortlicher:</label>
<select name="editBeauftragterId" id="createBeauftragterId"
ng-options="Beauftragter.Bezeichnung for Beauftragter in $scope.Beauftragter track by $scope.Beauftragter.BeauftragterId"
ng-model="$scope.Beauftragter.BeauftragterId"></select>
</div>
<div class="form-group">
<label for="createAuftragstext">Auftrag:</label>
<textarea class="form-control" rows="10" id="createAuftragstext" ng-model="Einzelauftrag.Auftragstext"> </textarea>
</div>
<button type="submit" class="btn btn-default">Auftrag erstellen</button>
</fieldset>
</form>
</div>
<div class="well" ng-show="showedit">
<div class="well-header">Einzelauftrag ändern</div>
<form role="form" ng-submit="BearbeiteEinzelauftrag()" ng-model="Einzelauftrag" name="einzelauftragedit" id="einzelauftragedit">
<fieldset>
<input type="text" id="editEinzelauftragsId" class="" ng-model="Einzelauftrag.EinzelauftragsId" />
<input type="text" id="editAlarmkalenderId" class="" ng-model="Einzelauftrag.AlarmkalenderId" />
<input type="text" id="editAlarmmassnahmeTrigraph" class="" ng-model="Einzelauftrag.AlarmmassnahmeTrigraph" />
<input type="text" id="editEinzelmassnahmeLfdAngabe" class="" ng-model="Einzelauftrag.EinzelmassnahmeLfdAngabe" />
<div class="form-group">
<label for="editBeauftragterId">Durchführungsverantwortlicher:</label>
<select name="editBeauftragterId" id="editBeauftragterId"
ng-options="beauftragter.Bezeichnung for beauftragter in data.Beauftragter track by Beauftragter.BeauftragterId"
ng-model="data.beauftragter.BeauftragterId"></select>
</div>
<div class="form-group">
<label for="editAuftragstext">Auftrag:</label>
<textarea class="form-control" rows="10" id="editAuftragstext" ng-model="Einzelauftrag.Auftragstext"> </textarea>
</div>
<button type="submit" class="btn btn-default">Änderung speichern</button>
</fieldset>
</form>
</div>
<div class="well" ng-show="showdelete">
<div class="well-header">Einzelauftrag löschen</div>
<form role="form" ng-submit="LoescheEinzelauftrag()" ng-model="Einzelauftrag" name="einzelauftragdelete" id="einzelauftragdelete">
<fieldset>
<input type="text" id="deleteEinzelauftragsId" class="" ng-model="Einzelauftrag.EinzelauftragsId" />
<input type="text" id="deleteAlarmkalenderId" class="" ng-model="Einzelauftrag.AlarmkalenderId" />
<input type="text" id="deleteAlarmmassnahmeTrigraph" class="" ng-model="Einzelauftrag.AlarmmassnahmeTrigraph" />
<input type="text" id="deleteEinzelmassnahmeLfdAngabe" class="" ng-model="Einzelauftrag.EinzelmassnahmeLfdAngabe" />
<div class="form-group">
<label for="deleteBeauftragterId">Durchführungsverantwortlicher:</label>
<input type="text" class="form-control" id="deleteBeauftragterId" ng-model="Einzelauftrag.BeauftragterId">
</div>
<div class="form-group">
<label for="deleteAuftragstext">Auftrag:</label>
<textarea class="form-control" rows="10" id="deleteAuftragstext" ng-model="Einzelauftrag.Auftragstext"> </textarea>
</div>
<button type="submit" class="btn btn-default">Auftrag löschen</button>
</fieldset>
</form>
</div>
<div ui-grid="row.entity.subsubGridOptions" style="height: 700px;"></div>
I believe you want to execute the method 'BearbeiteAuftrag' from 3rd Grid while clicking the hyperlink on second column. For that you can try the following changes.
On the 3rd Grid definition (row.entity.subsubGridOptions=), replace the line "appScopeProvider: $scope.subGridScope," with "appScopeProvider: $scope,"
Add the following function just after the "$scope.gridOptions =...."
$scope.BearbeiteAuftrag = function (einzelauftragId){
alert(einzelauftragId);
//Add code for the logic here with the parameter einzelauftragId
};
I'm having a problem with AngularJs. I have created a directive that $watch the model and it takes some action based on the model's current status. However, although during debugging I can see that the $watch is set, it is only being triggered after the model get valid at least once and I don't know why that is happening. Debugging it doesn't even gets into the $watch function when something is typed.
The code is below:
Directive:
(function() {
'use strict';
var app = angular.module('app');
app.directive('tooltipValidation', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
var tooltip = $(element).qtip({
content: {
text: element.next('div')
},
show: false,
hide: true
}).qtip('api');
scope.$watch(attrs.ngModel, function() {
if (ngModel.$invalid && ngModel.$dirty) {
tooltip.show();
} else {
tooltip.hide();
}
});
}
};
});
})()
HTML:
<div class="form-address clearfix" ng-show="isNewShippingAddress" ng-form="newShippingAddressForm">
<h3>Include new shipping address:</h3>
<div class="novo-endereco clearfix" id="newAddress">
<div class="required address apelido">
<label for="newShippingAddressAlias">Alias</label>
<input id="newShippingAddressAlias" name="newShippingAddressAlias" type="text" tooltip-validation ng-model="newShippingAddress.Alias" required ng-maxlength="32" />
<div data-ng-show="newShippingAddressForm.newShippingAddressAlias.$dirty && newShippingAddressForm.newShippingAddressAlias.$invalid">
<p data-ng-show="newShippingAddressForm.newShippingAddressAlias.$error.required">obligatory</p>
<p data-ng-show="newShippingAddressForm.newShippingAddressAlias.$error.maxlength">max 32 char</p>
</div>
</div>
<div class="required endereco">
<label for="newShippingAddressStreet">Street</label>
<input id="newShippingAddressStreet" name="newShippingAddressStreet" type="text" tooltip-validation ng-model="newShippingAddress.Street" required ng-maxlength="256" />
<div data-ng-show="newShippingAddressForm.newShippingAddressStreet.$dirty && newShippingAddressForm.newShippingAddressStreet.$invalid">
<p data-ng-show="newShippingAddressForm.newShippingAddressStreet.$error.required">obligatory</p>
<p data-ng-show="newShippingAddressForm.newShippingAddressStreet.$error.maxlength">max 256 char</p>
</div>
</div>
<div class="required cep">
<label for="newShippingAddressZipCode">ZipCode</label>
<input id="newShippingAddressZipCode" name="newShippingAddressZipCode" type="text" tooltip-validation ng-model="newShippingAddress.ZipCode" required ng-pattern="/^[0-9]{8}$/" />
<div data-ng-show="newShippingAddressForm.newShippingAddressZipCode.$dirty && newShippingAddressForm.newShippingAddressZipCode.$invalid">
<p data-ng-show="newShippingAddressForm.newShippingAddressZipCode.$error.required">obligatory</p>
<p data-ng-show="newShippingAddressForm.newShippingAddressZipCode.$error.pattern">8 digits</p>
</div>
</div>
<input type="submit" class="button grey" value="Save new address" data-ng-click="saveShippingAddress()" ng-disabled="newShippingAddressForm.$invalid" />
</div>
</div>
Regards,
dimello
Try:
scope.$watch(function(){
return ngModel.$viewValue; //Watch for view value (the value in your input)
}, function() {
if (ngModel.$invalid && ngModel.$dirty) {
tooltip.show();
} else {
tooltip.hide();
}
});
DEMO
Explanation:
When you type an invalid value into the input with ng-model, the underlying model is not updated, causing your scope.$watch(attrs.ngModel not being fired because you're watching for changes in the model. If you need to fire the function every time the input changes no matter it's valid or not, try the above solution.