Passing the value in directive to the ng-model. -angularjs - javascript

Hi Im trying to create a directive to pass some value to my ng-model,
in my directive i have a controller inside my directive and and i want to pass the value of it in my ng-model
Lets just say i have a string value, when i click the $scope.speakUP it should be pass it on the ng-model
.directive('speak', function(){
return {
restrict: 'A',
require: 'ngModel',
scope: true,
template: '<i ng-click = "speakUP()" class="icon ion-mic-a larger"></i>',
controller: function($scope, $element){
$scope.speakUP = function(){
$scope.passThisString = "Sample Data";
}
}
This is my HTML
<input type="text" ng-model="sampleModel" speak>

this is a quick example from where you can start implement your goals.
app.directive('inputField', function () {
return {
require: '?ngModel',
template: '<input ng-model="value" ng-change="onChange()"><i ng-click="speakUP()" class="icon ion-mic-a larger">click</i>',
link: function ($scope, $element, $attrs, ngModel) {
if (!ngModel) return;
$scope.speakUP = function(){
ngModel.$setViewValue('your data');
ngModel.$render();
}
$scope.onChange = function() {
ngModel.$setViewValue($scope.value);
};
ngModel.$render = function() {
$scope.value = ngModel.$modelValue;
};
}
};
});
HTML
<input-field name="sampleModel" ng-model="sampleModel"></input-field>

Related

AngularJS updating ng-repeat via input not working?

I'm trying to update values in a ng-repeat on a ng-model;
I have the current directive:
app.directive('myDirective', function () {
return {
require: 'ngModel',
restrict: 'E',
template: '<div ng-repeat="e in model"><input ng-model="e"/></div>',
scope: {
ngModel: '='
},
link: function($scope, elem, attrs, ngModelCtrl) {
$scope.$watch(function (){
return ngModelCtrl.$modelValue;
}, function (v) {
$scope.model = ngModelCtrl.$viewValue;
});
}
};
});
but it isn't updating the value as illustrated here:
http://plnkr.co/edit/E89sbXY0gUw53EmJobz0?p=preview
anybody knows what might be wrong?
http://plnkr.co/edit/2JwxNzBRQa1dzACoJIpF?p=preview
Had to replace $scope.model = ngModelCtrl.$viewValue; with scope.model = ngModelCtrl.$viewValue; and it works fine.
app.directive('myDirective', function () {
return {
require: 'ngModel',
restrict: 'E',
template: '<div ng-repeat="e in model"><input ng-model="e"/></div>',
scope: {
ngModel: '='
},
link: function(scope, elem, attrs, ngModelCtrl) {
console.debug()
scope.$watch(function (){
return ngModelCtrl.$modelValue;
}, function (v) {
scope.model = ngModelCtrl.$viewValue;
})
}
};
});
UPDATE: I converted 'stuff' to an array of objects and now it works:
http://plnkr.co/edit/2JwxNzBRQa1dzACoJIpF?p=preview
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.stuff = [{number: 1},{number: 2},{number: 3}];
});
app.directive('myDirective', function () {
return {
require: 'ngModel',
restrict: 'E',
template: '<div ng-repeat="e in model"><input ng-model="e.number"/></div>',
scope: {
ngModel: '='
},
link: function(scope, elem, attrs, ngModelCtrl) {
console.debug()
scope.$watch(function (){
return ngModelCtrl.$modelValue;
}, function (v) {
scope.model = ngModelCtrl.$viewValue;
console.log(scope.model)
})
}
};
});
#Kiwi ng-repeat creates a child scope and ng-model will use the property on the child scope, because ng-model binding will evaluate on the current scope. This is the reason why the json presented in the view doesn't change in your example as it was bound to a property on the child scope created by the ng-repeat directive.
Check this simple jsfiddle example I hope it will be of help to you.
<div ng-app="demo">
<div ng-controller="DefaultController as ctrl">
{{ctrl.numbers | json}}
<numbers numbers="ctrl.numbers"></numbers>
</div>
</div>
angular
.module('demo', [])
.controller('DefaultController', DefaultController)
.controller('NumbersController', NumbersController)
.directive('numbers', numbers);
function DefaultController() {
var vm = this;
vm.numbers = [1, 2, 3];
}
function numbers()
{
var directive = {
restrict: 'E',
scope: {
numbers: '='
},
template: '<div ng-repeat="number in vm.numbers"><input type="number" ng-model="vm.numbers[$index]"/></div>',
bindToController: true,
controller: NumbersController,
controllerAs: 'vm'
};
return directive;
}
function NumbersController() {
var vm = this;
}

change controller $scope from a directive

I have a controller:
function myController($scope) {
$scope.clicked = false;
}
and a directive:
function myDirective() {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
elem.bind('click', function() {
// need to update controller $scope.clicked value
});
},
template: '<div>click me</div>';
replace: true;
}
}
and I´m using it like this:
<div ng-controller="myController">
<my-directive></my-directive>
</div>
How can I change the controller value of $scope.clicked ?
thanks!
As you don't use isolated scope in your directive, you can use scope.$parent.clicked to access the parent scope property.
link: function(scope, elem, attrs) {
elem.bind('click', function() {
scope.$parent.clicked = ...
});
},
I would not recommend using scope.$parent to update or access the parent scope values, you can two way bind the controller variable that needs to be updated into your directive, so your directive becomes:
function myDirective() {
return {
restrict: 'E',
scope: {
clicked: '='
},
link: function(scope, elem, attrs) {
elem.bind('click', function() {
// need to update controller $scope.clicked value
$scope.clicked = !$scope.clicked;
});
},
template: '<div>click me</div>';
replace: true;
}
}
now pass this clicked from parent:
<div ng-controller="myController as parentVm">
<my-directive clicked="parentVm.clicked"></my-directive>
</div>
function myController() {
var parentVm = this;
parentVm.clicked = false;
}
I would recommend reading up on using controllerAs syntax for your controller as that would really solidify the concept of using two way binding here.
I like to use $scope.$emit for such purposes. It allows to send data from directive to the controller.
You should create custom listener in your controller:
$scope.$on('cliked-from-directive', function(event, data){
console.log(data)
})
As you can see, now you have full access to your controller scope and you can do whatever you want. And in your directive just to use scope.$emit
link: function(scope, elem, attrs) {
elem.bind('click', function() {
scope.$emit('cliked-from-directive', {a:10})
});
Here I've created jsfiddle for you

AngularJS: render HTML in directive controller

I'm writing a directive for creating text from templates, but I cannot get to render my final result into HTML. This is the directive:
.directive('description', function($timeout){
function descriptionCtrl(){
var self = this;
self.result = "";
self.init = function(value) {
console.log("template in directive",value);
self.finalValue = "<div>HI <input type='text' id='hi' /></div>";
};
}
return {
restrict: 'AE',
controller : descriptionCtrl,
controllerAs: 'dc',
scope: {
text: "="
},
replace: true,
template: "<div id='template'>{{dc.finalValue}}</div>",
link: function(scope, iElement, iAttrs, ctrl) {
scope.$watch("text", function(value){
if(value!==undefined){
$timeout(ctrl.init(value),0);
}
});
}
}
});
The data comes from the controller and once the user has chosen between some options, hence the $watch.
Thank you!
You should use ng-bind-html to bind html to the div
template: "<div id='template' ng-bind-html='dc.finalValue'></div>",

Initialize text input fields in angular directive

I have a directive which shows input fields and I want to initialize those fields with data from the server. The problem is that I can't do that while using ng-model.
Before using a directive I used in the controller something like $scope.field1 = $scope.first.field1
Here's my code. I simplified it for the sake of readability but the idea's here.
In my controller I have this code:
app.controller('MyController',
['$scope', 'myData', function($scope, myData) {
myData.then(function(data) {
$scope.first = data.first;
$scope.second = data.second;
});
}]);
Inside first and second I have 2 field: field1 and field2.
In in html code, I have this bit:
<h1>First</h1>
<my-directive info="first"></my-directive>
<h1>Second</h1>
<my-directive info="second"></my-directive>
The directive is as follows:
app.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
info: '='
},
templateUrl: 'static/js/myDirective.html',
link: function(scope, element, attrs) {
scope.doStuff = function() {
/* Do stuff with
scope.field1 and scope.field2 */
}
}
};
});
and the myDirective.html code:
<input type="text" ng-model="myfield1" />
<input type="text" ng-model="myfield2" />
<input type="submit" ng-click="doStuff()" />
If in myDirective.html I write:
<input type="text" value="info.field1" />
I can see the value fine.
Any ideas?
probably your directive initializes before your data loads. and your directive sees ng-model as an undefined variable. You are not using info directly in template so no auto $watch's for you :).
you need to $watch your info variable in directive and call your doStuff function on change.
note: i wouldn't recommend adding a controller to a directive just for this task. adding a controller to a directive is needed when you need to communicate with other directives. not for waiting async data
edit
you should do
app.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
info: '='
},
templateUrl: 'static/js/myDirective.html',
link: function(scope, element, attrs) {
scope.doStuff = function() {
/* Do stuff with
scope.field1 and scope.field2 */
}
scope.$watch('info', function(newValue){
scope.doStuff();
});
}
};
});
Check working demo: JSFiddle.
Define a controller for the directive and do the initialization inside it:
app.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
info: '='
},
controller: ['$scope', 'myData', function ($scope, myData) {
myData.then(function(data){
$scope.first = data.first;
$scope.second = data.second;
});
}],
...
},
Inside the directive, myfield1 and myfield2 don't exist. You are close to solving the issue by using info.field1 instead.
var myApp = angular.module('myApp', []);
//Faking myData here; in your example this would come from the server
var myData = {
first: {
field1: "FirstField1",
field2: "FirstField2"
},
second: {
field1: "SecondField1",
field2: "SecondField2"
}
};
myApp.controller('MyController', ['$scope', function($scope) {
$scope.first = myData.first;
$scope.second = myData.second;
}]);
myApp.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
info: '='
},
template: '<input type="text" ng-model="info.field1" /><input type="text" ng-model="info.field2" /><input type="submit" ng-click="doStuff()" />',
link: function(scope, element, attrs) {
scope.doStuff = function() {
alert('Info: ' + scope.info.field1 + ', ' + scope.info.field2);
}
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyController">
<h1>First</h1>
<my-directive info="first"></my-directive>
<h1>Second</h1>
<my-directive info="second"></my-directive>
</div>

How to get isolated scope of a directive with ngrepeat and two way bind?

How we can get particular isolated scope of the directive while calling link function from controller(parent)?
I am having a directive and repeating it using ng-repeat. Whenever a button in the directive template is clicked it will call a function- Stop() in directive controller which in-turn calls function test() in parent controller, inside test() it will call a method dirSample () in directive's link function.
When I print the scope inside dirSample(), it prints the scope of the last created directive not the one which called it.
How can I get the scope of the directive which called it?
Find the pluker here
.directive('stopwatch', function() {
return {
restrict: 'AE',
scope: {
meri : '&',
control: '='
},
templateUrl: 'text.html',
link: function(scope, element, attrs, ctrl) {
scope.internalControl = scope.control || {};
scope.internalControl.dirSample = function(){
console.log(scope)
console.log(element)
console.log(attrs)
console.log(ctrl)
}
},
controllerAs: 'swctrl',
controller: function($scope, $interval)
{
var self = this;
self.stop = function()
{
console.log($scope)
$scope.meri(1)
};
}
}});
full code in plunker
I've changed the binding of your function from & to = since you need to pass a parameter. This means some syntax changes are in order, and also you need to pass the scope along the chain if you want to have it all the way at the end:
HTML:
<div stopwatch control="dashControl" meri="test"></div>
Controller:
$scope.test = function(scope)
{
console.log(scope);
$scope.dashControl.dirSample(scope);
}
Directive:
.directive('stopwatch', function() {
return {
restrict: 'AE',
scope: {
meri : '=',
control: '='
},
templateUrl: 'text.html',
link: function(scope, element, attrs, ctrl) {
scope.internalControl = scope.control || {};
scope.internalControl.dirSample = function(_scope){
console.log(_scope);
}
},
controllerAs: 'swctrl',
controller: function($scope, $interval)
{
var self = this;
self.stop = function()
{
console.log($scope);
$scope.meri($scope);
};
}
}});
Plunker

Categories

Resources