I am having problem creating a child scope for each panel in an angularjs accordion.
The accordion is built up using data in this format:
$scope.accordionData = [
{'partial': 'desktop-ui/partials/test1.html', 'args':{'key1': $scope.args.users,'key2': 'http://www.sungard.com'}},
{'partial': 'desktop-ui/partials/test2.html', 'args':{'key1': $scope.args.contacts,'key2': 'http://financialsystems.sungard.com/solutions/asset-management'}}
];
The 2 objects in the array above contains
In my Directive, I use this code to create a new scope for each panel:
// element is the accordion and panels is a jQuery list of panels for the accordion and dataList is the data
function populatePanelsWithExtraArgs(element, dataList, panels) {
angular.forEach(dataList, function(data, index) { // for each panel
var dataArgs = data.args; // get the extra args
var panel = panels[index]; // get each panel from the jQuery list
panel = angular.element(panel); // convert to angular element
var childScope = panel.scope(); // create a new scope HERE IS THE PROBLEM
childScope.args = dataArgs; // add the args to each panel's scope.
});
}
The line 'panel.scope();' does not in fact create a new scope. The scope's id is the same as the main scope's id. Also, the first arg is overwritten by the second arg.
If I try this:
panel.scope().$new()
This works but then it adds 'args' to something called $$childTail (I'm using chrome debugger):
scope.$$childTail.args
Then this means that {{args.key1}} doesn't work anymore because the variable args is no longer on the main scope but on this $$childTail thing.
doThe solution to creating a new scope for each panel in the accordion was to compile the panel DOM element with its own directive, thus automatically creating a unique scope.
In the markup (in the Accordion Directive) I add a new class Directive panel-data:
var panel = '<div class="accordion-body collapse in panel-data"><div class="sg-accordion-inner-wrapper"><div class="accordion-inner"></div></div></div>');
Then I created the new panelData Directive:
angular.module('sgComponents').directive('panelData', [function () {
return {
restrict: 'C', // a class Directive
scope: true // with its own unique scope
};
}]);
Then I used jQuery to select each 'accordion-inner' which is where the content goes:
var innerElement = thisElement.find('.accordion-inner');
Next I got the scope of each one:
var innerScope = innerElement.scope();
Then I called an utility function to add the content:
var accordionConent = addContentToInclude(contentBuffer, content);
Then I compiled the accordionContent with the innerScope and appended it to the innerElement panel:
innerElement.append($compile(angular.element(accordionContent))(innerScope));
Finally, when I came to add the extra arguments to the panel in the populateExtraArguments() function, all I had to do was get the panel, turn it into an angular element, get its scope (the panelData scope in fact) and then add the extra arguments to the scope:
// element is the accordion and panels is a jQuery list of panels for the accordion
and dataList is the data
function populatePanelsWithExtraArgs(element, dataList, panels) {
angular.forEach(dataList, function(data, index) { // for each panel
var dataArgs = data.args; // get the extra args
var panel = panels[index]; // get each panel from the jQuery list
panel = angular.element(panel); // convert to angular element
var childScope = panel.scope(); // get the scope
childScope.args = dataArgs; // add the args to each panel's scope.
});
}