Pass variable to directive that is restricted to attribute - angularjs

I have this directive:
.directive('myDate', ['$timeout', '$rootScope', '$locale',
function ($timeout, $rootScope, $locale) {
'use strict';
return {
restrict: 'A',
scope: {
customDate: '='
},
// the rest part of directive...
};
}
]);
I know how to pass a variable to directive that is restricted to element. But that approach doesn't work when the directive is given as attribute:
<div class="input-group date" my-date custom-date="testDate">
<input type="text" class="form-control" ng-model="dateFrom" />
</div>
Where:
scope.testDate= new Date('2015-01-13')
How can I get it work?

For the most part, your code should work. Here is a working plunker for the rest. There were just a few small issues with the OP. In the controller, the property that is bound to the directive attribute must be of the same name (scope.date should have been scope.testDate) etc.
The controller:
app.controller('Ctrl', function($scope) {
$scope.testDate = new Date('2015-01-13')
});
The directive:
app.directive('myDate', ['$timeout', '$rootScope',
function ($timeout, $rootScope) {
'use strict';
return {
restrict: 'A',
scope: {
customDate: '='
},
link(scope) {
console.log(scope.customDate);
}
};
}
]);
The HTML:
<body ng-app="myApp">
<div ng-controller="Ctrl">
<div class="input-group date" my-date custom-date="testDate">
<input type="text" class="form-control" ng-model="dateFrom" />
</div>
</div>
</body>

Related

Getting controls of forms inside a directive

I'm working on an AngularJS app and created two forms inside a directive. I want to reset both form's $submitted by $setSubmitted(false), however, the problem is that I cannot get two controls at the same time inside the directive controller.
Referred to this solution How to handle multiple forms present in a single page using AngularJS. However, the solution is for a controller, not for a directive.
(function () {
'use strict';
angular
.module('app')
.directive('multiForms', multiForms);
function multiForms() {
return {
restrict: "A",
scope: {
},
controller: function ($scope) {
$scope.functions = {
submit1: submit1,
submit2: submit2,
resetForms: resetForms
};
function resetForms() {
$scope.form1.$setSubmitted(false);
$scope.form2.$setSubmitted(false);
}
},
replace: false,
templateUrl: 'pathToTheHtml.html'
}
}
})();
<div>
<form name="form1" ng-submit="functions.submit1()">
<ng-form name="form1">
<input type="text" ng-model="text1">
<button type="submit">Submit1</button>
</ng-form>
</form>
<form name="form-2" ng-submit="functions.submit2()">
<ng-form name="form2">
<input type="text" ng-model="text2">
<button type="submit">Submit2</button>
</ng-form>
</form>
<button ng-click="functions.resetForms()"></button>
</div>
The expected results is to set $submitted value to false for both form1 and form2. The actual result is both $scope.form1 and $scope.form2 are undefined.
I was playing around and this actually worked. I added vm and binded with the view.
(function () {
'use strict';
angular
.module('app')
.directive('multiForms', multiForms);
function multiForms() {
return {
restrict: "A",
scope: {
},
controller: function ($scope) {
const vm = this;
vm.functions = {
submit1: submit1,
submit2: submit2,
resetForms: resetForms
};
function resetForms() {
vm.form1.$setPristine();
vm.form2.$setPristine();
}
},
controllerAs: 'vm',
bindToController: true,
replace: false,
templateUrl: 'pathToTheHtml.html'
}
}
})();
<div>
<form name="vm.form1" ng-submit="vm.functions.submit1()">
<ng-form name="form1">
<input type="text" ng-model="vm.data.text1">
<button type="submit">Submit1</button>
</ng-form>
</form>
<form name="vm.form-2" ng-submit="vm.functions.submit2()">
<ng-form name="form2">
<input type="text" ng-model="vm.data.text2">
<button type="submit">Submit2</button>
</ng-form>
</form>
<button ng-click="vm.functions.resetForms()"></button>
</div>

Angularjs How to get value of input[text] in controller

I want to get value of input[text] in my controller when data is changed as this source code:
(function () {
'use strict';
var app = angular.module('app', ['ngMaterial']);
app.controller('ScanDataCtrl', function ($scope) {
$scope.getScannedData = function () {
console.log($scope.formScanData.scanDataIReceipt);
};
});
app.directive('scanDataBScan', function ($mdDialog, $sce, $http) {
return {
restrict: 'C',
link: function (scope, element, attrs) {
element.on('click', function () {
scope.getScannedData();
// => the value always undefined
});
}
};
});
});
<div ng-controller="ScanDataCtrl">
<form accept-charset="UTF-8" class="form-inline formScanData" name="formScanData">
<input ng-model="formScanData.scanDataIReceipt" type="text" required>
<md-input-container>
<md-button ng-model="scanDataBScan" class="md-raised md-primary scanDataBScan">Scan</md-button>
</md-input-container>
</form>
</div>
the result of this source code is always undefine
Please help me.
If I ask wrong or bad with my English, I am sorry.
Thank you!
Use the ng-change directive:
<input ng-model="formScanData.scanDataIReceipt" type="text"
ng-change="getScannedData()" required>
For more information, see AngularJS ng-change Directive API Reference.
(function () {
'use strict';
var app = angular.module('app', ['ngMaterial']);
app.controller('ScanDataCtrl', function ($scope) {
$scope.getScannedData = function (data) {
console.log(data);
};
});
app.directive('scanDataBScan', function ($mdDialog, $sce, $http) {
return {
restrict: 'C',
link: function (scope, element, attrs) {
element.on('click', function () {
scope.getScannedData();
// => the value always undefined
});
}
};
});
});
<div ng-controller="ScanDataCtrl">
<form accept-charset="UTF-8" class="form-inline formScanData" name="formScanData">
<input ng-model="formScanData.scanDataIReceipt" type="text" required>
<md-input-container>
<md-button ng-model="scanDataBScan" ng-click="getScannedData(formScanData.scanDataIReceipt)" class="md-raised md-primary scanDataBScan">Scan</md-button>
</md-input-container>
</form>
</div>

Component binding not working : Angularjs

Hi I'm trying to create a component, it works fine in controller, however not binding values to view.
My Component is as below
app.component("bdObjects", {
templateUrl: "app/templates/components/BusinessObjects.html",
controller: ["$scope", "$http", "$log", "API_ROOT", "VisDataSet",
function ($scope, $http, $log, API_ROOT, VisDataSet) {
$scope.fnAdd = function() {
$scope.objectId = "";
$scope.objectName = "Test Object";
console.log($scope.objectName);
}
$scope.cancelAdd = function() {
if($scope.items.length > 0) {
$log.info($scope.items[0]);
$scope.fnPopulateForm($scope.items[0]);
}
}
}],
bindings: {
data: "=",
objectId: "=",
objectName: "="
}
});
My Template
<div class="general-form">
<input type="hidden" name="id" ng-model="objectId">
<label>Name:</label>
<br>
<input class="form-control" name="name" placeholder="Name" ng-model="objectName">
<br>
</div>
So on add button I tried to assign value to input box. but it's not taking. and I want to make that two way binding. so later I'll have save button, so changing the value in TextBox will replace in Controller.
Thanks.
In controller, change $scope by this or some alias, e.g.
controller: ["$scope", "$http", "$log", "API_ROOT", "VisDataSet",
function ($scope, $http, $log, API_ROOT, VisDataSet) {
var ctrl = this;
ctrl.fnAdd = function() {
ctrl.objectId = "";
ctrl.objectName = "Test Object";
console.log(ctrl.objectName);
}
// Not sure about items: you haven't defined it,
// neither fnPopulateForm...
ctrl.cancelAdd = function() {
if(ctrl.items.length > 0) {
$log.info($scope.items[0]);
ctrl.fnPopulateForm(ctrl.items[0]);
}
}
}],
And in view, use the default controller binding i.e $ctrl
<div class="general-form">
<input type="hidden" name="id" ng-model="$ctrl.objectId">
<label>Name:</label>
<br>
<input class="form-control" name="name" placeholder="Name" ng-model="$ctrl.objectName">
<br>
</div>
You can also change $ctrl into whatever you want in a controllerAs declaration of the component, i.e.
app.component("bdObjects", {
templateUrl: "app/templates/components/BusinessObjects.html",
controller: ["$scope", "$http", "$log", "API_ROOT", "VisDataSet",
function ($scope, $http, $log, API_ROOT, VisDataSet) {
//...
}],
controllerAs: 'bd',
bindings: {
//...
}
});
and in the view:
I tried with $timeout() and it got working.
Hey check this JS fiddle
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="namesCtrl">
<input type="hidden" name="id" ng-model="objectId">
<label>Name:</label>
<br>
<input class="form-control" name="name" placeholder="Name" ng-model="objectName">
<br>
<button ng-click="fnAdd()">
button
</button>
</div>
<script>
angular.module('myApp', []).controller('namesCtrl', function($scope) {
$scope.fnAdd = function() {
$scope.objectId = "";
$scope.objectName = "Test Object";
console.log($scope.objectName);
}
$scope.cancelAdd = function() {
if ($scope.items.length > 0) {
$log.info($scope.items[0]);
$scope.fnPopulateForm($scope.items[0]);
}
}
});
</script>

User Input won't duplicate/display in directive template

Why are the user inputted values not duplicating when a user types into an input?
The user input works and duplicates when the HTML is separate from a custom directive template as shown below and in this fiddle: http://jsfiddle.net/Lvc0u55v/7069/ .
<div ng-controller="LeaseTemplateController">
<div class="leasespecial">
<div class="firstsec">
<div class="percNumber">
<h1 id="perId" ng-repeat="bb in percent_id">{{bb.value}}</h1>
</div>
</div>
<h2>Lease Special Template</h2>
<form>
<div class="form-group" ng-repeat="cc in percent_id">
<div class="input-group">
<input class="form-control input" type="text" placeholder="Enter Percent" ng-model="cc.value">
</div>
</div>
</form>
</div>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('LeaseTemplateController', ['$scope', function($scope) {
//Lease Special Template
$scope.percent_id = [{
value: '20'
}];
}]);
</script>
However, instead I'm trying to insert it using two different directive templates as shown in this fiddle: http://jsfiddle.net/Lvc0u55v/7068/
<div lease-text-directive>
</div>
<div lease-input-directive>
</div>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('LeaseTemplateController', ['$scope', function($scope) {
//Lease Special Template
$scope.percent_id = [{
value: '20'
}];
}]);
myApp.directive('leaseTextDirective', function() {
return {
restrict: 'A',
template: '<div class="leasespecial" ng-controller="LeaseTemplateController">\
<div class="firstsec">\
<div class="percNumber">\
<h1 id="perId" ng-repeat="bb in percent_id">{{bb.value}}</h1>\
</div>\
</div>'
};
});
myApp.directive('leaseInputDirective', function() {
return {
restrict: 'A',
template: '<h2>Lease Special Template</h2>\
<form ng-controller="LeaseTemplateController">\
<div class="form-group" ng-repeat="cc in percent_id">\
<div class="input-group">\
<input class="form-control input" type="text" placeholder="Enter Percent" ng-model="cc.value">\
</div>\
</div>\
</form>'
};
});
</script>
Why are the values not duplicating over in the second example and would you suggest a better practice than this?
I believe your experiencing the separation of scopes. Your directives have a different scope than your controller so it knows nothing. Try injecting your rootscope or scope like myApp.directive('leaseInputDirective', function($rootScope, $scope)
got it working now
var myApp = angular.module('myApp', []);
myApp.controller('LeaseTemplateController', function($scope,$rootScope) {
//Lease Special Template
$rootScope.percent_id = [{
value: '20'
}];
});
myApp.directive('leaseTextDirective', function() {
return {
restrict: 'E',
replace: true, // Replace with the template below
transclude: true, // we want to insert custom content inside the directive
template: '<div class="leasespecial" ng-controller="LeaseTemplateController">\
<div class="firstsec">\
<div class="percNumber">\
<h1 id="perId" ng-repeat="bb in percent_id">{{bb.value}}</h1>\
</div>\
</div>'
};
});
myApp.directive('leaseInputDirective', function() {
return {
restrict: 'E',
replace: true, // Replace with the template below
transclude: true, // we want to insert custom content inside the directive
template: '<div><h2>Lease Special Template</h2>\
<form ng-controller="LeaseTemplateController">\
<div class="form-group" ng-repeat="cc in percent_id">\
<div class="input-group">\
<input class="form-control input" type="text" placeholder="Enter Percent" ng-model="cc.value">\
</div>\
</div>\
</form></div>'
};
});
<lease-text-directive>
</lease-text-directive>
<!-- leaseTextDirective -->
<lease-input-directive>
</lease-input-directive>

AngularJS : How can I use an object id to create a set of form fields

edit: I worked it out, I need to use [tray.id] instead of {{tray.id}}
I have an array of "trays" and I want to build a form to edit them, but I'm not sure how to set the ng-model for each tray so I can differentiate between them.
This does not work, angular doesn't like me putting {{tray.id}} into ng-model
<div ng-repeat="tray in formData.trayData">
<div class="form-group">
<label class="control-label" for="formData.trays.{{tray.id}}.name">Name:</label>
<div class="controls">
<input type="text" class="form-control" name="tray.{{tray.id}}.name" ng-model="formData.trays.{{tray.id}}.name" placeholder="Name">
</div>
</div>
<div class="form-group">
<label class="control-label" for="formData.trays.{{tray.id}}.seal">Seal:</label>
<div class="controls">
<input type="text" class="form-control" name="tray.{{tray.id}}.seal" ng-model="formData.trays.{{tray.id}}.sealed" placeholder="Seal">
</div>
</div>
</div>
In my controller I setup formData using a json object from an API
$scope.formData.trayData = $scope.surgeryDetails.trays;
$scope.formData.trays = [];
And here is what I get from {{formdata.trayData}}
[{"id":8,"name":"Tray 1","seal":"Foo","status_id":9},{"id":9,"name":"Tray 2","seal":"Bar","status_id":9}]
I'm glad you figured the ngModel part out on your own.
However, I also just wanted to mention that you may not be getting what you are expecting when/if you go to handle validation using the name attribute.
There is currently a bug in Angular that prevents dynamic element validation. The workaround is provided in the comments by Thinkscape, or here is a plunker with the correct code. Here is the main part:
angular.module('myModule', [])
.config(function($provide) {
$provide.decorator('ngModelDirective', function($delegate) {
var ngModel = $delegate[0],
controller = ngModel.controller;
ngModel.controller = ['$scope', '$element', '$attrs', '$injector',
function(scope, element, attrs, $injector) {
var $interpolate = $injector.get('$interpolate');
attrs.$set('name', $interpolate(attrs.name || '')(scope));
$injector.invoke(controller, this, {
'$scope': scope,
'$element': element,
'$attrs': attrs
});
}
];
return $delegate;
});
$provide.decorator('formDirective', function($delegate) {
var form = $delegate[0],
controller = form.controller;
form.controller = ['$scope', '$element', '$attrs', '$injector',
function(scope, element, attrs, $injector) {
var $interpolate = $injector.get('$interpolate');
attrs.$set('name', $interpolate(attrs.name || attrs.ngForm || '')(scope));
$injector.invoke(controller, this, {
'$scope': scope,
'$element': element,
'$attrs': attrs
});
}
];
return $delegate;
});
})

Resources