I have a directive as follows,
var myApp = angular.module('myApp', []);
myApp.directive("checkTextCombo", [
"$compile", function($compile) {
return {
restrict: "E",
replace: true,
scope: {
source: '#',
},
link: function(scope, element, attrs) {
scope.rows = eval('(' + scope.source + ')');
},
templateUrl: "../templates/check-text-combo/check-text-combo.html",
controller: function($scope){
$scope.$watch('$scope.rows', function() {
console.log($scope.rows);
});
}
};
}
]);
And a template:
<div ng-repeat="row in rows">
<input type="checkbox" ng-checked="row.checked"/> <label value="{{row.label}}">{{row.label}}</label><input type="textbox" value="{{row.value}}" ng-disabled="!row.checked"/>
</div>
index.html consists of
<check-text-combo source="[{'value':'varsh','label':'name','checked': true}, {'value':'bij','label':'name','checked': false}]"></check-text-combo>
My problem is that, I can a create a template with ng-repeat, but after binding, when I change something in the template, it doesn't change elsewhere. How can I get the modified value?
Got it working after adding ng-model
<div ng-repeat="row in rows">
<input type="checkbox" ng-checked="row.checked" ng-model="row.checked"/> <label value="{{row.label}}">{{row.label}}</label><input type="textbox" value="{{row.value}}" ng-model="row.value" ng-disabled="!row.checked"/>
</div>
You should to change your $watch definition:
$scope.$watch('rows', function() {
// ^
// Here
// rows instead of $scope.rows
console.log($scope.rows);
}, true);
// ^
//and here
// third parameter to true - observed variable is an Object
Related
I am getting a value from a function in controller1. I want to set this value to controller2's directive's template. I am confused on how to use scope in this to achieve the same.
Html
<body ng-app = "myApp" ng-controller="parentcontroller as ctrl">
<div class ="boardcanvas" style ="overflow-x:auto;">
<div id = "board">
<list-wrapper ng-repeat="task in ctrl.tasks track by $index" class ="listwrapper" id = "listwrapper"></list-wrapper>
<add-list-controls class = "controls" tasks ="ctrl.tasks" ng-show ="ctrl.listcontrolarea"></add-list-controls>
</div>
</div>
</body>
Controller1 and its Directive:
angular.module('myApp')
.controller('listController', ['$scope','$compile','$http', function($scope, $compile, $http){
'ngInject';
$scope.tasks=[];
$scope.cardarr =[];
vm.addme = function(){
console.log(vm);
console.log($scope.tasks);
$scope.tasks.push({title: $scope.title, cardarr: []});
}
}])
.directive('addListControls', function() {
return {
restrict: 'E', // Element directive'
controller: 'listController as listctrl2',
scope: { tasks: "=",
cardarr: "="},
template: `<textarea ng-model= "listctrl2.title" placeholder ="Add a List" id="input" style = "position:absolute"></textarea>
<button id="controlbutton" class ="btn btn success" style = "position:absolute" ng-click="listctrl2.addme()">Save
</button>`,
};
});
Controller2 and its Directive:
.controller('listWrapperController', ['$scope','$compile','$http', function($scope, $compile, $http){
'ngInject';
$scope.tasks=[];
}])
.directive('listWrapper', function() {
return {
restrict: 'E', // Element directive
scope:{
tasks: '='
},
controller: 'listWrapperController as listctrl',
template: `<div id="titlebox">
<b class ="card1" tasks="listctrl.task" id ="cardtitle">
{{task.title}} // set the value from controller1 here
</b>
</div> `
};
});
You are initalizing the $scope.tasks array on both controllersand this override the original $scope.task reference (ctrl.tasks) that is set by directive definititon.
Try comment or initialize only if undefined
$scope.tasks= $scope.tasks || [];
$scope.cardarr = $scope.cardarr || [];
The listWrapper directive must be changed andd translate the ng-repeat to its template:
HTML
<list-wrapper tasks="ctrl.tasks"></list-wrapper>
listWrapper directive
(...)
.directive('listWrapper', function() {
return {
restrict: 'E', // Element directive
scope:{
tasks: '='
},
controller: 'listWrapperController as listctrl',
template:
`<div id="titlebox" ng-repeat="task in tasks track by $index" class ="listwrapper" id = "listwrapper">
<b class ="card1" id ="cardtitle">
{{task.title}} // set the value from controller1 here
</b>
</div> `
};
});
I'm new in AngularJS, currently I'm working on custom input directive with a label.
I refer to one article in stack overflow but encountered problem.
The running code is on fiddle:
http://jsfiddle.net/luneyq/bpN9b/18/
Core code is as below:
<!doctype html>
<html>
<head>
<script src="../common/angular.js"></script>
</head>
<body>
<div ng-app="myApp">
<div ng-controller="MainController">
<my-input type="number" name="valueNumber1" ng-model="valueNumber1" label="Age" ng-change="change()" ng-click="click()"></my-input>
<div id="result">a</div>
</div>
</div>
<script>
var app = angular.module("myApp", []);
app.controller('MainController', function($scope, $window){
$scope.valueNumber1 = 10;
$scope.change = function() {
document.getElementById("result").innerHTML = 'change:' + $scope.valueNumber1;
};
$scope.click = function() {
document.getElementById("result").innerHTML = 'click:' + $scope.valueNumber1;
};
});
app.directive('myInput', function() {
return {
require: '^ngModel',
restrict: 'EA',
scope: {
ngModel: '=',
name: '#name',
label: '#label'
},
replace: true,
transclude: true,
//priority: 10,
template: '<div>' +
'<label for="{{ name }}">{{label}}</label>' +
'<input id="{{ name }}" ng-model="ngModel" />' +
'</div>',
compile: function(tElement, tAttrs, transclude) {
var tInput = tElement.find('input');
// Move the attributed given to 'custom-input' to the real input field
angular.forEach(tAttrs, function(value, key) {
if (key.charAt(0) == '$' || key == "class")
return;
tInput.attr(key, value);
tInput.parent().removeAttr(key);
});
tElement.removeAttr('ng-model');
return;
}
};
})
</script>
</body>
</html>
My problems are:
1. ng-click and ng-change not working on the input
2. ng-model="ngModel" on input element, why ngModel is used here? if I change ngModel to aaa, the initial value for the input disappeared
3. attributes copy in compile function removed the dash(-) signal, ng-click is copied as ngClick.
I'm not sure is this the cause of this problem.
Can anyone help on this problem?
Your problem was click and change methods not in your isolate scope - BUT you are not making use of Angular's two way binding here - instead simply use ng-bind on your result div - here's a fiddle http://jsfiddle.net/bpN9b/20/
var app = angular.module("myApp", []);
app.controller('MainController', function($scope, $window){
$scope.valueNumber1 = 10;
});
app.directive('myInput', function() {
return {
require: '^ngModel',
restrict: 'EA',
scope: {
ngModel: '=',
name: '#name',
label: '#label'
},
replace: true,
priority: 10,
template: '<div class="cbay-input-div">' +
'<label for="{{ name }}">{{label}}</label>' +
'<input id="{{ name }}" ng-model="ngModel" />' +
'</div>',
compile: function(tElement, tAttrs, transclude) {
console.log(tAttrs);
var tInput = tElement.find('input');
// Move the attributed given to 'custom-input' to the real input field
angular.forEach(tAttrs, function(value, key) {
//console.log(key + " = " + value);
if (key.charAt(0) == '$' || key == "class")
return;
tInput.attr(key, value);
tInput.parent().removeAttr(key);
});
tElement.removeAttr('ng-model');
return;
}
};
});
here's the template
<div ng-app="myApp">
<div ng-controller="MainController">
<my-input type="number" name="valueNumber1" ng-model="valueNumber1" label="Age" ng-change="change(this)" ng-click="click(this)"></my-input>
<div id="result" ng-bind="valueNumber1">a</div>
</div>
</div>
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>
This is my scenario,
view:
<div data-ng-controller="MyModuleController">
<div ng-repeat="a in range() track by $index" >
<ty-project idx="$index+1" ng-model="projects[$index]" ></ty-project>
</div>
</div>
controller:
$scope.projects= [];
$scope.range = function() {
// return some random number - it does not really matter for the purpose
};
ty-project is just a directive
angular.module('mymodule').directive('tyProject', [
function() {
return {
templateUrl: 'modules/mymodule/directives/typrojectTemplate.html',
restrict: 'E',
scope: {
idx: '='
},
link: function postLink(scope, element, attrs) {
}
};
}
]);
typrojectTemplate is a simple template with 2 inputs,as following:
<div>
<label>Project_{{idx}} name</label>
<input type="text" name="project.name" ng-model="project.name"/>
</div>
<div >
<label >Project_{{idx}} total </label>
<input type="number" name="project.total" ng-model="project.total" />
</div>
this is my controller
angular.module('mymodule').controller('MyModuleController', ['$scope',
function($scope) {
$scope.projects: [] ;
$scope.save = function() {
console.log(projects);
};
$scope.range = function() {
var n= 2;// todo: return random number..
return new Array(n);
};
}
]);
so in case range method return 2
there will be 2 projects object
each project has name and total attributes.
how can I bind the projects to the controller?
Thanks.
hay you have to pass the scope from the controller to the directive. The directive will pass this scope to the template.
you could do this in your directive:
scope:{
project: '=ngModel'//will pass it to the Template.
idx: '=' //
}
i dont know, whether u assigned the controller to the view.
I'm trying to implement two way binding for custom directive in angularJs. Somehow its not working.
html file
<div ng-app='myApp'>Outside directive
<input type='text' ng-model='outAttr'>{{outAttr}}</br>
<div my-directive some-attr='outAttr'></div>
</div>
js file
var myApp = angular.module('myApp', []);
myApp.directive('myDirective', function () {
return {
restrict: 'A,
replace: true,
scope: {
inAttr: '=someAttr';
},
template: "<div><input type='text' ng-model='inAttr'>\
{{inAttr}}</div>"
}
})
Somehow its not working. here is JSFiddle link. Can someone help me pointing out my mistake. Thanks.
Few syntax errors. The logic of your code is OK - jsFiddle
var myApp = angular.module('myApp', []);
myApp.directive('myDirective', function() {
return {
restrict: 'A', // missing '
replace: true,
scope: {
inAttr: '=someAttr' // no ;
},
template: '<div><input type="text" ng-model="inAttr">{{inAttr}}</div>' // no break
};
});