Angularjs dynamically adding controls - angularjs

Im trying to adding dynamically $scope
app.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function (html) {
ele.html(html);
$compile(ele.contents())(scope);
});
}
};});
and my HTML;
<select dynamic="myOption_{{ item.RowId }}" id="select_{{ item.RowId }}" multiple class="chosen" data-ng-model="selectedOption" data-placeholder="Select" data-ng-change="ChangeTopic()"
chosen="directiveOptions"
ng-options="item.Id as item.tag for item in optionsFromQuery"
style="width:100%;">
</select>
angular;
var appsx = "";
for (var i = 0; i < result.item.length; i++) {
var rowIds = parseInt(result.item[i].RowId);
appsx = '<option value="" selected>' + result.item[i].Tags + '</option>';
var controlName = 'myOption_' + rowIds;
controlName = appsx;
}
Example; if I try to $scope.myOption_100 = appsx; it's working but I cannot make dynamically scope
$scope.controlName = 'myOption_' + rowIds; like that.

Try scope.$observe(attrs.dynamic.....

Related

isolate scope communication from directive to directive?

I am new to AngularJS and got confused with directive concept.
I am updating scope.markers in my second directive via $scope.delete function but changes are not reflecting on first directives,as I am using two way data binding isolate scope, so it should reflect. any solution will be a great help.
I have my first directive as:
app.directive('damageDiagram', function () {
return {
retrict: 'AE',
scope: {
imgsrc: '=', markers: '=', pointsrc: '=', dtype:'='
},
templateUrl: 'app/components/inspections/damage-diagram.html',
link: function (scope, element, attrs) {
}
}
});
and second directive as:
app.directive('damageMarker', function ($mdDialog,inspectionService,$timeout) {
return {
restrict: 'AE',
require: '?^damageDiagram',
scope: {
marker: '=',
pointsrc: '=',
dtype:'=',
markers: '='
},
template: '<img ng-src="{{pointsrc}}" />',
link: function (scope, elem, attr) {
elem.on("click",function(e){
showDialog();
function showDialog($event) {
var parentEl = angular.element(document.body);
$mdDialog.show ({
parent: parentEl,
targetEvent: $event,
template:
'<form name="clientForm" novalidate >'+
'<md-dialog aria-label="List dialog">' +
' <md-dialog-content>'+
'<md-input-container>'+
'<md-select ng-model="dtypeValue" class="dialog-close" placeholder="Select dtype">'+
'<md-option ng-repeat="opt in dtype">{{opt}}</md-option>'+
'</md-select>'+
'</md-input-container>'+
'<md-input-container class="md-block">'+
'<label>Comment</label>'+
'<input required name="name" ng-model="comment" class="dialog-close">'+
'<div ng-messages="clientForm.name.$error">'+
'<div ng-message="required">This is required.</div>'+
'</div>'+
'</md-input-container>'+
' </md-dialog-content>' +
' <div class="md-actions" layout="row" layout-align="end center">' +
' <md-button ng-click="closeDialog()" class="md-primary">' +
' Close' +
' </md-button>' +
'<md-button ng-disabled="clientForm.$invalid" ng-click = "save()" class="md-primary">'+
'Save'+
'</md-button>'+
'<md-button ng-disabled="clientForm.$invalid" ng-click = "delete()" class="md-primary">'+
'Delete'+
'</md-button>'+
' </div>' +
'</md-dialog>'+
'</form>',
controller: DialogController
});
function DialogController($scope, $mdDialog) {
$scope.dtypeValue = scope.dtype[scope.marker.dtype.toUpperCase()];
$scope.dtype = scope.dtype;
$scope.comment = scope.marker.comment;
$scope.marker = scope.marker;
$scope.closeDialog = function() {
$mdDialog.hide();
}
$scope.save = function(){
console.log($scope.marker.id);
console.log($scope.dtypeValue);
console.log($scope.comment);
var dataSend = {};
dataSend.id = $scope.marker.id;
dataSend.comment = $scope.comment;
for(var key in $scope.dtype) {
if($scope.dtype[key] == $scope.dtypeValue) {
dataSend.dtype = key;
}
}
inspectionService.updateDiagram(dataSend).then(function(response){
console.debug("response ; "+response);
$mdDialog.hide();
scope.marker.id = response.id;
scope.marker.comment = response.comment;
scope.marker.dtype = response.dtype;
});
}
$scope.delete = function(){
var dataSend = {};
dataSend.id = $scope.marker.id;
var param = {};
param.inspection=$scope.marker.inspection;
inspectionService.deleteDiagramMarker(dataSend).then(function(response){
inspectionService.getDiagram(param).then(function(response){
$timeout(function() {
scope.$apply(function(){
scope.markers = response.results;
})
},2000);
console.debug("response ; "+response);
$mdDialog.hide();
});
});
}
}
}
});
console.log(scope.marker.top, scope.marker.left, elem);
}
}
});
My html code for damage-diagram directive is as follows:
<damage-diagram imgsrc="imgsrc" pointsrc="pointsrc" dtype="dtype"
markers="inspection.damage_diagram">
</damage-diagram>
and my html code for damage-directive is as follow:
<div style="position:relative">
<img id="23467129" ng-src="{{imgsrc}}" style="position:relative" width="100%" />
<div ng-repeat="marker in markers"
marker="marker"
markers="markers"
dtype="dtype"
pointsrc="pointsrc"
damage-marker>
</div>
</div>
controller is as follows:
app.controller('InspectionDetailCtrl', ['$scope', 'inspectionService', '$stateParams', 'Restangular','$rootScope',
function ($scope, inspectionService, $stateParams, Restangular, $rootScope) {
$scope.updateDamageImage = {};
$scope.insp_id = $stateParams.inspId;
$scope.damageImagesShow = false;
$scope.comments = [];
$scope.types = [];
$scope.selectTypeDelete = false;
$scope.commentDelete = false;
$scope.selectTypeDeleteBefore = true;
$scope.commentDeleteBefore = true;
init($scope.insp_id);
console.log("Fetching details for scope", $scope.insp_id);
function init(insp_id)
{
inspectionService.inspections.customGET(insp_id, {type: 'full'})
.then(function (data) {
$scope.inspection = data;
}, function (err) {
$scope.inspection = null;
});
}
$scope.pointsrc="app/components/inspections/pointer.png";
$scope.dtype = {
'S': 'Scratch (minor)',
'DS': 'Deep Scratch',
'D': 'Dents',
'WD': 'Wheel Damage',
'CW': 'Cracked Window',
'FT': 'Flat Tire',
'BL': 'Broken (lights)'
};
}]);
First of all two way binding in directive doesn't works like that any change reflected in main controller can be seen in directive but not other way any change in directive won't be reflected in main controller.
But there is a solution you can create an object in main controller
var x={};
x.value='to be passed in directive'
then you use same variable in directive since only once instance of object is created so any change in any directive will be reflected everywhere.

AngularJS Access Global Variable Under Directive

I have a global variable like following.
var Lightbox = {};
............
Lightbox.openModal = function (newImages, newIndex, modalParams) {
...............
}
I would like to access this variable under directives like the following way.
app.directive('productBuyers', ['Product', function(Product) {
return {
restrict : 'E',
scope : {},
template : '<div>' +
'<p class="product-buyers-f bold" ng-show="photos.length">Others:</p>' +
'<
'<div class="product-buyer square" ng-click="openLightboxModal($index)" ng-repeat="photo in photos | limitTo:3" ng-style="{\'background-image\':\'url(\' + photo.image + \')\'}"></div>' +
'<div class="clear"></div>' +
'</div>' +
'</div>',
link : function($scope, element, attrs) {
$scope.photos = [];
function getImages() {
}
$scope.openLightboxModal = function (index) {
Lightbox.openModal($scope.photos, index);
};
getImages();
}
}
}]);
I have tried by passing "$window" to the directive parameter and also using scope but it's not working. It's showing undefined "Lightbox".
Try window.Lightbox and also window.Lightbox.openModal = function(...)

Directive function not running

I have this directive:
angular.module('colab.dropdown', []).directive('colabDropdown', function(){
return {
restrict: 'A',
transclude: true,
scope: {
ddlist: '=listtoshow',
model: '=modeltosave',
displayField: '=listfieldtoshow',
fieldtoSave: '=listfieldtosave'
},
link: function(scope, element, attrs) {
var ddlist = scope.ddlist,
model = scope.model,
displayField = scope.displayField,
fieldtoSave = scope.fieldtoSave,
rowIdx = scope.rowIndex;
rowIdx = null;
for(var i=0;i < ddlist.length;i++){
if(ddlist[i][attrs.listfieldtosave] == model){
rowIdx = i;
}
}
if(rowIdx !== null){
scope.displayField = ddlist[rowIdx][attrs.listfieldtoshow];
}
console.log(scope.displayField);
scope.selectItem = function(unit) {
console.log(unit);
// var idx = scope[attrs.listtoshow].indexOf(unit);
// scope[attrs.modeltosave] = unit[attrs.listfieldtosave];
// scope.listfieldtoshow = unit[attrs.listfieldtoshow];
};
}
}
});
here is my template:
<div class="radio">
<label>
<input type="radio"
name="chickenEgg"
ng-value="mm.id"
ng-model="formData.chickenEgg"
ng-change="selectItem(mm)"
>
{{mm.name}} - {{mm.year}}
</label>
</div>
I am not able to do the following:
run function selectedItem() in my template when I click the radio.
display the {{displayField}} in the DOM. I can display it in the console (line 38 of the directive) but not in the DOM. see the plunker console**
I can run the selectItem() if I don't have the scope:{...} in the directive.
http://plnkr.co/edit/wuLmJs5f6hVhPEP7OqKS?p=preview
Thank you.
You need to add you add your selectItem() function to angular-hovercard.js file.
$scope.selectItem = function(item) {
console.log(item);
}
Check it Out

generating a variable-length dropdown based on input value in an AngularJS directive

I want to provide a page selection directive that generates "Page [ 1 ] of x". The number of pages in the dropdown is dependent upon values passed into the directive, so it can't be part of a static template. I'm having a difficult time figuring out how/where to generate the <select><option>...</select>.
I have tried, unsuccessfully, to do it via:
an $observe (and $watch) in link
a function added to $scope in controller, which returns $compile(markup)($scope) (This gives the error Error: [$parse:isecdom] Referencing DOM nodes in Angular expressions is disallowed!)
a sub-directive for the <select> element (The link $observer never seemed to get the recordCount updates, regardless of inherited or shared scope.)
ng-repeat in the template
Here's my mangled code, as it currently stands.
HTML
<x-pager
record-count="{{recordCount}}"
page-size="pageSize"
page-number="pageNumber"
set-page="selectPage(page)"
></x-pager>
JS
module.directive("pager", ["$compile",
function ($compile)
{
return {
template: "<div class='pager' ng-show='recordCount > pageSize'>\
{{recordCount}} results\
<button>« Prev</button>\
page <select>\
<option>#</option>\
</select> of {{calcPages()}}\
<button>Next »</button>\
</div>",
replace: true,
restrict: "E",
scope: {
recordCount: "#",
pageSize: "=",
pageNumber: "=",
setPage: "&"
},
link: function (scope, element, attrs)
{
/*
* We can't build the page selection dropdown until
* we know how many records we have. Register an
* observer to do this when recordCount changes.
*/
attrs.$observe("recordCount", function (recCnt)
{
var html;
var pages;
var i;
if (angular.isDefined(recCnt)) {
html = "<select>\n";
pages = Math.ceil(scope.recordCount / scope.pageSize);
for (i=1; i<=pages; i++) {
html += " <option value='" + i + "'>" + i + "</option>\n";
}
html += "</select>";
console.log("generatePageSelect html", html);
html = $compile(html)(scope);
// add the template content
// angular.element("select.page-selector").html(html);
// template: page <select class='page-selector'></select> of {{calcPages()}}\
}
});
},
controller: function ($scope)
{
$scope.calcPages = function ()
{
return Math.ceil($scope.recordCount / $scope.pageSize);
};
function genPagesArray ()
{
var pages = $scope.calcPages();
var i;
var pagesArray = [];
for (i=0; i<pages; i++) {
pagesArray.push(i);
}
return pagesArray;
}
$scope.pagesArray = genPagesArray();
console.log("$scope.pagesArray", $scope.pagesArray);
// template: page {{generatePageSelect()}} of {{calcPages()}}\
$scope.generatePageSelect = function ()
{
var html = "<select>\n";
var pages = $scope.calcPages();
var i;
for (i=1; i<=pages; i++) {
html += " <option value='" + i + "'>" + i + "</option>\n";
}
html += "</select>";
return $compile(html)($scope);
};
}
};
}
]);
To expand on my comment from earlier, here's a directive that does (most of) what you want it to do.
angular.module('Test', []).controller('TestCtrl', function($scope) {
$scope.pageSize = 10;
$scope.pageNumber = 1;
$scope.recordCount = 30;
}).directive("pager", function () {
return {
template: '<div class="pager" ng-show="recordCount > pageSize">\
{{recordCount}} results\
<button ng-click="pageNumber = pageNumber - 1" ng-disabled="pageNumber <= 1">« Prev</button>\
page <select ng-model="pageNumber" ng-options="i for i in pages"></select> of {{totalPages}}\
<button ng-click="pageNumber = pageNumber + 1" ng-disabled="pageNumber >= totalPages">Next »</button>\
</div>',
replace: true,
restrict: "E",
scope: {
recordCount: "#",
pageSize: "=",
pageNumber: "=",
setPage: "&"
},
link: function (scope, element, attrs) {
attrs.$observe("recordCount", function (count) {
if (angular.isDefined(count)) {
scope.recordCount = parseInt(count);
var i;
scope.totalPages = Math.ceil(scope.recordCount / scope.pageSize);
scope.pages = [];
for (i=1; i<=scope.totalPages; i++) {
scope.pages.push(i);
}
}
});
}
}
});
Plunkr here.

How to make AngularJS compile the code generated by directive?

Please help me on, How can we make AngularJS compile the code generated by directive ?
You can even find the same code here, http://jsbin.com/obuqip/4/edit
HTML
<div ng-controller="myController">
{{names[0]}} {{names[1]}}
<br/> <hello-world my-username="names[0]"></hello-world>
<br/> <hello-world my-username="names[1]"></hello-world>
<br/><button ng-click="clicked()">Click Me</button>
</div>
Javascript
var components= angular.module('components', []);
components.controller("myController",
function ($scope) {
var counter = 1;
$scope.names = ["Number0","lorem","Epsum"];
$scope.clicked = function() {
$scope.names[0] = "Number" + counter++;
};
}
);
// **Here is the directive code**
components.directive('helloWorld', function() {
var directiveObj = {
link:function(scope, element, attrs) {
var strTemplate, strUserT = attrs.myUsername || "";
console.log(strUserT);
if(strUserT) {
strTemplate = "<DIV> Hello" + "{{" + strUserT +"}} </DIV>" ;
} else {
strTemplate = "<DIV>Sorry, No user to greet!</DIV>" ;
}
element.replaceWith(strTemplate);
},
restrict: 'E'
};
return directiveObj;
});
Here's a version that doesn't use a compile function nor a link function:
myApp.directive('helloWorld', function () {
return {
restrict: 'E',
replace: true,
scope: {
myUsername: '#'
},
template: '<span><div ng-show="myUsername">Hello {{myUsername}}</div>'
+ '<div ng-hide="myUsername">Sorry, No user to greet!</div></span>',
};
});
Note that the template is wrapped in a <span> because a template needs to have one root element. (Without the <span>, it would have two <div> root elements.)
The HTML needs to be modified slightly, to interpolate:
<hello-world my-username="{{names[0]}}"></hello-world>
Fiddle.
Code: http://jsbin.com/obuqip/9/edit
components.directive('helloWorld', function() {
var directiveObj = {
compile:function(element, attrs) {
var strTemplate, strUserT = attrs.myUsername || "";
console.log(strUserT);
if(strUserT) {
strTemplate = "<DIV> Hello " + "{{" + strUserT +"}} </DIV>" ;
} else {
strTemplate = "<DIV>Sorry, No user to greet!</DIV>" ;
}
element.replaceWith(strTemplate);
},
restrict: 'E'
};
return directiveObj;
});
Explanation: The same code should be used in compile function rather than linking function. AngularJS does compile the generated content of compile function.
You need to create an angular element from the template and use the $compile service
jsBin
components.directive('helloWorld', ['$compile', function(compile) {
var directiveObj = {
link: function(scope, element, attrs) {
var strTemplate, strUserT = attrs.myUsername || "";
console.log(strUserT);
if (strUserT) {
strTemplate = "<DIV> Hello" + "{{" + strUserT +"}} </DIV>" ;
} else {
strTemplate = "<DIV>Sorry, No user to greet!</DIV>" ;
}
var e = angular.element(strTemplate);
compile(e.contents())(scope);
element.replaceWith(e);
},
template: function() {
console.log(args);
return "Hello";
},
restrict: 'E'
};
return directiveObj;
}]);

Resources