Reputation: 4449
What I need
A chain of screens that each open the next screen on a button click. Each previous screen must be collapsed and the new screen must be added by loading a partial view from the MVC backend.
What I have
An AngularJS controller with the following function:
self.AddChild = function (uri, targetContainerId, collapseTitle, breadCrumbContainerId) {
var target = $("#" + targetContainerId);
if (target != 'undefined' && target != undefined && target.length > 0) {
apiService.Get(uri).then(function (viewData) {
self.CollapsePreviousChild(self.ChildCount);
// Increase childcount by 1
self.ChildCount += 1;
// Set HTML data
var html = '<div id="collapsibleScreen-"' + self.ChildCount + ' class="open">' + viewData + '</div>';
target.html(html);
// Update screens collapse status
self.UpdateScreenBreadCrumb(collapseTitle, breadCrumbContainerId);
});
};
}
The UpdateScreenBreadCrumb function works and is otherwise unrelated.
It is called (for instance) like this:
self.AddChild("/Partials/View1", "targetContainer", "View", "breadCrumbContainer");
What it does
The content of the View, a form, is loaded, the breadcrumb is updated correctly.
What I need fixed
On the partial view that was loaded, there is a button defined like this:
<button class="btn btn-primary" ng-click="AddPartialView()">Add partial view</button>
Clicking that button has no effect whatsoever. If I add a console.log('Code was here.') to the AddPartialView(), it is not logged. Setting the ng-click value directly to alert('hello') has no effect either.
There are no errors of any kind visible.
Any suggestions on how to make this button work?
Upvotes: 0
Views: 1802
Reputation: 4449
I've looked into $compile, as suggested by Itamar L. and got it to work. The samples I found were using Directives as well, so I implemented them anyway:
angular.module('directives.api').directive("PartialViewLoader", [
'$compile',
'chainedScreensService',
function (
$compile,
chainedScreensService) {
return {
restrict: 'A',
scope: {
view: '=',
parent: '='
},
controller: function() {
},
link: function (scope, element, attrs) {
chainedScreensService.GetPartialView(attrs.view).then(function (viewData) {
var linkFunc = $compile(viewData);
var content = linkFunc(scope);
element.append(content);
if (attrs.parent != 'undefined' && attrs.parent != undefined && attrs.parent.length > 0) {
chainedScreensService.CollapsePartialByIdentifier(attrs.parent);
}
});
}
}
}
]);
I use it like this:
<div ng-controller="collapseController">
<div id="breadCrumbContainer" style="display: inline"></div>
<div id="mainContainer">
<div id="personContainer" partial-view-loader view="persoon" parent="" class="open"></div>
</div>
</div>
That in itself displays the first page, which has a button to the next, as mentioned. The associated function, found in the collapseController, is this:
self.AddNextScreen = function (parentViewIdentifier, targetContainerId, breadCrumbContainerId) {
self.AddChildByDirective("NextScreen", parentViewIdentifier, targetContainerId, breadCrumbContainerId);
}
The code for AddChildByDirective:
self.AddChildByDirective = function (viewIdentifier, parentViewIdentifier, targetContainerId, breadCrumbContainerId) {
var html = '<div id="' + viewIdentifier + 'Container" fvl-partial-view-loader view="' + viewIdentifier + '" parent="' + parentViewIdentifier + '" class="open"></div>';
var target = $('#' + targetContainerId);
var linkFunc = $compile(html);
var content = linkFunc($scope);
target.append(content);
self.UpdateScreenBreadCrumb(viewIdentifier, breadCrumbContainerId);
}
At this point I still need to test actual chaining, but this works to load a new screen and collapse the previous.
Upvotes: 1
Reputation: 519
In regards to your question, you are adding HTML that isn't compiled by Angular. You need to use $compile on your newly added HTML element and then bind it to a scope. The $compile() function returns a link() function which you use to bind a scope to. Example:
$compile(new-element)(scope-to-bind-to)
NOTE: You should not be manipulating the DOM via a controller. This is considered bad practice. You should be using a custom directive or some combo of Angular directives (ngIf, ngSwitch, ngInclude). I recommend watching AngularJS best practices.
Upvotes: 1