Angular JS reset custom directive - angularjs

I want to reset this directive(clear the file chosen) when clear button is clicked. Currently even though when clear button is clicked , the file chosen is still exits and its not cleared.
test.html
<form class="form form-basic" id="testForm" name="testForm">
<div class="row">
<label class="col-md-6 control-label">File :</label>
<div class="col-md-6">
<div class="form-group">
<input type="file" ng-model="test" on-read-file="loadContent($fileContent)" />
</div>
</div>
</div>
<button class="btn btn-primary" ng-click="clear()">Clear</button>
</div>
directive.js
fileAccessModule.directive('onReadFile', function ($parse) {
return {
restrict: 'A',
scope: false,
link: function (scope, element, attrs) {
var fn = $parse(attrs.onReadFile);
element.on('change', function (onChangeEvent) {
var reader = new FileReader();
reader.onload = function (onLoadEvent) {
scope.$apply(function () {
fn(scope, {$fileContent: onLoadEvent.target.result});
});
};
reader.readAsText((onChangeEvent.srcElement || onChangeEvent.target).files[0]);
});
}
};
});
testController.js
testControllerModule.controller('testController', function ($scope, $log, $location, deviceDetailsService) {
$scope.clear = function () {
$scope.connectionParams = null;
};
$scope.loadContent = function ($fileContent) {
$scope.connectionParams.privateKey = $fileContent;
};
});

Not sure what $scope.connectionParams is that by setting it to null, you are expecting the form to be reset.
However, to achieve the same form reset logic, you can resort to Javascript's built-in reset() method, but, in an Angularized manner.
To do so, you can define a directive for this as such:
/* ... */
.directive('formReset', function() {
return {
restrict: 'E',
replace: true,
scope: {
formName: '#'
},
link: function(scope, iElement) {
iElement.on('click', function() {
var form = document.querySelector('[name="' + scope.formName + '"]');
form.reset();
});
}
},
template: '<button type="button">Reset</button>'
})
and, use it in your form as in the following:
<form-reset form-name="yourFormName"></form-reset>
Demo

Related

Controller Function Not called inside Directive

I have a controller function and I cannot call it inside the directive. I am trying hard. is there any thing Else i am failing to do? please tell me. I have included my code here. I have searched many places followed many answers and now I am stuck at this
(function () {
var app = angular.module("featureModule", ['ngRoute']);
//
app.directive('myGoogleAutocomplete', function () {
return {
replace: true,
require: 'ngModel',
scope: {
ngModel: '=',
googleModel: '=',
onSelect: '&?', // optional callback on selected successfully: 'onPostedBid(googleModel)'
},
template: '<input class="form-control" type="text" style="z-index: 100000;" autocomplete="on">',
link: function ($scope, element, attrs, model)
{
var autocomplete = new google.maps.places.Autocomplete(element[0], googleOptions);
google.maps.event.addListener(autocomplete, 'place_changed', function () {
$scope.$apply(function () {
var place = autocomplete.getPlace();
if (!place.geometry)
{
// User entered the name of a Place that was not suggested and pressed the Enter key, or the Place Details request failed.
model.$setValidity('place', false);
//console.log("No details available for input: '" + place.name + "'");
return;
}
$scope.googleModel = {};
$scope.googleModel.placeId = place.place_id;
$scope.googleModel.latitude = place.geometry.location.lat();
$scope.googleModel.longitude = place.geometry.location.lng();
$scope.googleModel.formattedAddress = place.formatted_address;
if (place.address_components) {
$scope.googleModel.address = [
$scope.extract(place.address_components, 'route'),
$scope.extract(place.address_components, 'street_number')
].join(' ');
}
model.$setViewValue(element.val());
model.$setValidity('place', true);
if (attrs.onSelect)
{
//how to call controller function here?
$scope.onSelect({ $item: $scope.googleModel });
}
});
});
}
}
});
app.controller("featureController", function($scope,$http,$rootScope,close,ModalService,NgMap) {
console.log($rootScope.permService);
$scope.onSelect=function(val)
{
console.log(val);
}
});
<my-google-autocomplete id="address" name="address" ng-model="task.house_no" google-model="model.googleAddress"
on-select="vm.onSelectGoogleAddress($item)" autocomplete="off" required>
</my-google-autocomplete>
There is no onSelectGoogleAddress() function in the controller. I see only onSelect() function. Change on-select value passed in the html.
<my-google-autocomplete id="address" name="address" ng-model="task.house_no" google-model="model.googleAddress"
on-select="onSelect($item)" autocomplete="off" required>
</my-google-autocomplete>
You can bind callback event by using elemet inside link function.
Here is the example . Hope it helps.
Let the controller having callback function from directive as below
app.controller('MainCtrl', function($scope) {
$scope.SayHello=function(id){
alert(id);
}
});
Let the directive
app.directive('dirDemo', function () {
return {
scope: {
okCallback: '&'
},
template: '<input type="button" value="Click me" >',
link: function (scope, element, attrs) {
var param='from directive';
element.bind('click', function () {
scope.$apply(function () {
scope.okCallback({id:param});
});
});
}
}
});
HTML is
<body ng-controller="MainCtrl">
<div dir-demo
ok-callback="SayHello(id)"
</div>
</body>
Working plunker https://plnkr.co/edit/RbFjFfqR1MDDa3Jwe8Gq?p=preview

how to get directive attribute values while using submit button

Here i created sample program using angularJs directive and controller, in directive i m created some attributes like (print-Display="true" is-Silent="false" is-Authentication="false" is-Download="false"), how to get this attribute values while using submit button (Controller)
Thanks in advance
var app = angular.module('myApp', []);
app.directive('telPrint', ['$http',
function($http) {
return {
restrict: 'AEC',
require: 'ngModel',
scope: {
ngModel: '=',
printDisplay: '#',
canShow: '#',
isChecked: '#',
isAuthentication: '#',
isDownload: '#',
},
template: '<span > <input type="checkbox" name="ngModel" ng-checked="checked"> <label > Print </label></span> ',
controller: function($scope, $rootScope) {
$scope.printOption = [];
$scope.Authentication = $scope.isAuthentication;
$scope.Silent = $scope.isSilent;
$scope.Download = $scope.isDownload;
},
link: function(scope, iElement, iAttrs, ngModelController) {
var labelName = iAttrs.getString;
var labelName = labelName.split(",");
var language = labelName[0]; // Language EN or Fr
var fieldlabelName = labelName[1]; // Label Name
var fieldmoduleName = labelName[2]; // Module Name (global or local)
if (iAttrs.isSilent == "true") {
scope.checked = true;
} else if (iAttrs.isSilent == "false") {
scope.checked = false;
}
console.log(iAttrs.printDisplay)
}
};
}
])
app.controller('myCtrl', function($scope) {
$scope.printcontr = function() {
console.log("Inside ")
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<div class="row col-sm-12">
<div class="col-sm-12">
<tel-Print ng-model="taxmaster.print" get-string="lbl,print,common" print-Display="true" is-Silent="true" is-Authentication="false" is-Download="true"></tel-Print>
</div>
<div>
<div class="col-sm-12">
</div>
<div class="col-sm-12">
<input type="submit" value="Save" ng-click="printcontr()" />
</div>
</div>
</body>
By scope.$parent, you can access $scope of the controller:
var app = angular.module('myApp', []);
app.directive('telPrint', ['$http',
function($http) {
return {
restrict: 'AEC',
require: 'ngModel',
scope: {
ngModel: '=',
printDisplay: '#',
canShow: '#',
isChecked: '#',
isAuthentication: '#',
isDownload: '#',
},
template: '<span > <input type="checkbox" name="ngModel" ng-checked="checked"> <label > Print </label></span> ',
controller: function($scope, $rootScope) {
$scope.printOption = [];
$scope.Authentication = $scope.isAuthentication;
$scope.Silent = $scope.isSilent;
$scope.Download = $scope.isDownload;
},
link: function(scope, iElement, iAttrs, ngModelController) {
var labelName = iAttrs.getString;
var labelName = labelName.split(",");
var language = labelName[0]; // Language EN or Fr
var fieldlabelName = labelName[1]; // Label Name
var fieldmoduleName = labelName[2]; // Module Name (global or local)
if (iAttrs.isSilent == "true") {
scope.checked = true;
} else if (iAttrs.isSilent == "false") {
scope.checked = false;
}
console.log(iAttrs.printDisplay);
// Set data
scope.$parent.language = labelName[0];
scope.$parent.fieldlabelName = labelName[1];
scope.$parent.fieldmoduleName = labelName[2];
}
};
}
])
app.controller('myCtrl', function($scope) {
$scope.printcontr = function() {
console.log("Inside ");
//Retrive data
console.info('language=', $scope.language);
console.info('fieldlabelName=', $scope.fieldlabelName);
console.info('fieldmoduleName=', $scope.fieldmoduleName);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<div class="row col-sm-12">
<div class="col-sm-12">
<tel-Print ng-model="taxmaster.print" get-string="lbl,print,common" print-Display="true" is-Silent="true" is-Authentication="false" is-Download="true"></tel-Print>
</div>
<div>
<div class="col-sm-12">
</div>
<div class="col-sm-12">
<input type="submit" value="Save" ng-click="printcontr()" />
</div>
</div>
</div>
</body>
I would suggest if you have a need to fetch directive attributes inside parent controller then while defining directive's scope instead of using '#', use '=' (two way binding) so that whatever you will be changing any attribute in the directive, you will always have those values in the parent controller.
app.directive('telPrint', ['$http',
function($http) {
return {
restrict: 'AEC',
require: 'ngModel',
scope: {
ngModel: '=',
printDisplay: '=',
canShow: '=',
isChecked: '=',
isAuthentication: '=',
isDownload: '=',
}...

directive reacting to attribute change

I have a directive, with an attribute :
html :
<my-directive id="test" myattr="50"></my-directive>
js :
myApp.directive('myDirective', function() {
var link = function(scope, element, attrs) {
scope.$watch('myattr', function(value) {
element.attr('myattr', value);
});
scope.change = function() {
// some code
};
};
return {
restrict: 'E',
template: '<input type="text" ng-change="change()" ng-model="myattr"/>',
scope: {myattr: '='},
link: link
};
});
My goal would be to keep myattr and the value of the input equal. With element.attr('myattr', value) I can force myattr to have the correct value, but how am I supposed to update the input when myattr changes?
For example, in this jsfiddle, when clicking on the button, I try to do :
$('#test').attr('myattr', Math.random() * 100);
But I can't find a way to 'catch' the change from within the directive.
I would like some help modifying the jsfiddle so that :
the function change is called after the jquery call.
the value of the input is always equal to myattr
You need to store the value of myattr as a property on a scope not as a value on an attribute.
Your directive is correct you need to also attach a controller.
var myApp = angular.module('myApp', []);
myApp.controller('MainController', function ($scope) {
$scope.calculate = function () {
// your logic here
alert($scope.val);
}
});
myApp.directive('myDirective', function() {
var link = function(scope, element, attrs) {
scope.change = function() {
console.log("change " + scope.myattr);
};
};
return {
restrict: 'E',
template: '<input type="text" ng-change="change()" ng-model="myattr"/>',
scope: {
myattr: '='
},
link: link
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MainController">
My Value: {{val}} <br/>
<button type="button" ng-click="calculate()">ok</button>
<my-directive id="test" myattr="val"></my-directive>
</div>
</div>

ng-hide doesn't work within hierarchy directives

I'm a newbie angular and will be happy to have some help here.
I'm struggeling to find out why I cannot setup one directive that is setting up an attribute hide="true" or "false" that will be used within the directive (Rank) as a parameter to change the inner directive (label) ng-hide to hide the label.
I tried everything
The outer directive (Rank) html:
<div>
<img src="/Components/Directives/images/blue_{{RankValue}}.svg" tooltip="{{RankValue}}/4" />
<label-info ng-hide="hide" header="{{header}}"></label-info>
</div>
The outer directive (Rank) directive java script:
angular.module('reusableDirectives')
.directive('Rank', function () {
return {
restrict: 'E',
scope: {
hide: '='
},
link: function (scope, element, attrs) {
scope.safeApply(scope.RankValue = scope.$eval(attrs.value));
scope.safeApply(scope.hidelabel = "true");
if (attrs.hidelabel == "false")
scope.safeApply(scope.hidelabel = "false");
scope.hidelabel = attrs.hide;
},
templateUrl: '/Components/Directives/Rank.html'
};
})
.controller('rankCtrl', ['scope', function ($scope) {
}]);
The inner directive (label) Html:
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3>{{header}}</h3>
</div>
<div class="modal-body">
<div ng-bind-html="items"></div>
</div>
</div>
<div class="modal-footer">
<div style="float:left;">
<button class="btn btn-primary" ng-click="ok()">Close</button>
</div>
</div>
</script>
<div>
<div class="fs-labelInfo-text">
{{header}}
</div>
<img class="fs-labelInfo-img"
ng-click="update(header)"
src="Components/Directives/images/questionMark.png" />
</div>
The inner directive (Label) directive java script:
angular.module('reusableDirectives')
.directive('labelInfo', function () {
return {
restrict: 'E',
scope: {
isolatedLabelHide: '#hidelabel'
},
controller: function ($scope, $element, $modal, $log, $http, $rootScope, myService) {
$scope.header = "header attribute";
$scope.caption = "label caption";
$scope.ok = function (header) {
myService.getLabelInfo(header).then(function (data) {
//this will execute when the AJAX call completes.
$scope.items = data;
console.log(data);
$scope.open();
});
};
$scope.open = function () {
$log.info('open');
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
resolve: {
header: function () {
return $scope.header;
},
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function () {
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
},
link: function (scope, element, attrs) {
scope.header = attrs.header;
},
templateUrl: '/Components/Directives/LabelInfo.html'
};
});
angular.module('reusableDirectives')
.controller('ModalInstanceCtrl', function ($scope, $modalInstance, header, items) {
$scope.items = items;
$scope.header = header;
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
The html that I'm using to test is:
One example to show the label:
<rank hide="false" value="3.5"></rank>
Another example to show the label:
<rank value="3.5"></rank>
example to hide will be:
<rank hide="true" value="3.5"></rank>
Thank you for your effort.
Best regards,
Chen
You set the scope property name as "hideLabel":
scope.hidelabel = attrs.hide;
So, you need to use "hideLabel" for the ng-hide attribute:
<label-info ng-hide="hideLabel" header="{{header}}"></label-info>
And you need to declare the ng-hide in your "labelInfo" directive template:
<div ng-hide="hideLabel">
(This "div" is the one that comes above <div class="fs-labelInfo-text"> at /Components/Directives/LabelInfo.html.)

how to do live responsive custom validation of form fields in angular

I have a form field that I want validated against a rest api as the user types in the form field. Sort of like an auto-complete but an auto-verify instead. I've started to lay some of the code down in angular but not sure how to observe the input onchange in angular or how to set the inavlid property of things.
Here's what I have so far
app.directive('purchaseCode', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
if (CODE_REGEXP.test(viewValue)) {
//how do I get the $http context/scope to to an ajax request here?
$http.get('check/user.code').success(function(data) {
ctrl.$setValidity('purchase_code', data.is_valid);
});
return viewValue;
} else {
ctrl.$setValidity('purchase_code', false);
return undefined;
}
});
}
};
});
function Controller($scope, $routeParams, $http) {
$scope.master = {};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.isUnchanged = function(user) {
return angular.equals(user, $scope.master);
};
$scope.reset();
}
and the HTML
<div class="container" ng-app>
<form no-validate id="myform" name='form' action="/upload" method="POST" role="form" ng-controller="Controller">
<div class="form-group has-error">
<label class="control-label" for="purchase_code">Purchase code</label>
<input type="text" class="form-control" id="purchase_code" placeholder="purchase code"
ng-model="user.code"
purchase-code
name="code">
</div>
<button type="submit" class="btn btn-block btn-primary" ng-click="update(user)"
ng-disabled="form.$invalid || isUnchanged(user)">Submit</button>
</form>
</div>
What do I do to have it watch the event of the form field being changes. Also a bonus question: how do I keep it from showing the invalid/dirty state until it gets to be more than 3 characters in length?
I tried looking at the custom validator sample on http://docs.angularjs.org/guide/forms but it doesn't seem to work if you copy and paste their code in verbatim.
I just needed to pass in $http into the method
app.directive('purchaseCode', function($http) {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
if (CODE_REGEXP.test(viewValue)) {
$http.get('check/user.code').success(function(data) {
ctrl.$setValidity('purchase_code', data.is_valid);
});
return viewValue;
} else {
ctrl.$setValidity('purchase_code', false);
return undefined;
}
});
}
};
});

Resources