Reputation: 1680
I'm attempting to build a directive to handle the rendering of a repeating list of speakers. The end goal here is to have the page automatically reflect the updates made in a modal.
The problem I'm appearing to see here is that the speakers
object doesn't appear to make it into the template.
This is the function that populates speakers
. It's called in the modal's promise. speakers
is a collection of speaker
objects. The data comes back as expected.
$scope.updateSpeakersList = function () {
factory.callGetService("GetSpeakers?eventId=" + $scope.event.eventId)
.then(function (response) {
var fullResult = angular.fromJson(response);
var serviceResponse = JSON.parse(fullResult.data);
$scope.speakers = serviceResponse.Content;
if ($scope.speakers === null) {
$scope.hasSpeakers = false;
} else {
$scope.hasSpeakers = ($scope.speakers.length > 0);
}
LogErrors(serviceResponse.Errors);
},
function (data) {
console.log("Unknown error occurred calling GetSpeakers");
console.log(data);
});
}
// other code... then this
modalInstance.result.then(function (savedSpeaker) {
console.log("BEGIN modalInstance.result");
$scope.savedSpeaker = savedSpeaker;
console.log("$scope.savedSpeaker = " + $scope.savedSpeaker);
$scope.updateSpeakersList();
console.log("END modalInstance.result");
}, function () {
console.log("Modal dismissed at: " + new Date());
});
The HTML looks like this.
<div class="container" ng-show="hasSpeakers">
<div class="row">
<speaker-cards data="speakers"></speaker-cards>
</div>
</div>
The directive is pretty simple.
.directive("speakerCards", function() {
return {
restrict: "E",
templateUrl: "/Apps/Event/Templates/_default/speaker-cards.html",
scope: {
data: "="
}
};
});
The "speaker cards" template is a bit more complex than this, but you should get the point.
<!-- BEGIN speaker cards -->
<div ng-repeat="speaker in speakers | orderBy: 'SpeakerName'">
<div class="clearfix" ng-if="$index % 3 == 0"></div>
<div class="col-sm-4">
<div class="card">
<span class="speaker-name">{{speaker.SpeakerName}}</span><br/>
<span class="speaker-title">{{speaker.CompanyTitle}}</span><br/>
<span class="speaker-company">{{speaker.CompanyName}}</span>
</div>
</div>
</div>
<!-- END speaker cards -->
Besides the speakers not appearing, the reason I don't think that speakers
is making it into the template, is because the resulting markup looks like this.
Upvotes: 1
Views: 65
Reputation: 6608
The issue in your code is in the scope definition of your custom directive.
scope: {
data: "="
}
With this, it will look for a data
attribute on your directive like <speaker-cards data='speakers'>
and assigns it to data
property on the isolated scope created for this directive.
But you're looking for speakers
in your template.
<div ng-repeat="speaker in speakers | orderBy: 'SpeakerName'">
But there's no speakers
defined in your current directive scope, there's only data
property, so you can fix it by changing your template like below.
<div ng-repeat="speaker in data | orderBy: 'SpeakerName'">
You can also fix this by changing your scope definition to capture data
attribute from directive as speakers
in your directive scope.
myApp.directive("speakerCards", function() {
return {
restrict: "E",
templateUrl: "template.html",
scope: {
speakers: "=data"
}
};
});
With this, you don't have to change your template. Here's a sample Pen to illustrate this.
Upvotes: 5
Reputation: 5462
Are you defining your var $scope.speakers
when the Angular Ctrl first run?
If you only define speakers
at later stage eg: when the function updateSpeakersList
returns with data, Angular might not have configured speakers
and might have no watchers in it (due to how dependency injection works in AngularJs).
Add the following line when the angular controller first run (configuration time)
$scope.speakers = [];
Upvotes: 1