Reputation: 6166
I am creating a scavenger hunt editor that will contain many different questions. Also, each question can be of different type. Therefore, I have one array of questions and I do an ng-repeat to show all the questions.
To do so, I have a javascript object that represent a Question. This question can be inherited by different question types.
I have one specific question type, that is slidingPuzzle
, which will require an image to be uploaded. My problem arrives here, I want to be able to call a function, inside this object, when the input file changes.
I want here to put the emphasis on the fact that it cannot be a general function declared in the scope !
Here's how my structure looks like (http://plnkr.co/edit/lnJ8rAlpP0xJ3aM2HZ7o?p=preview):
HTML:
<div class="question" ng-repeat="question in scavengerHunt.questions">
<div class="chooseQuestionType">
Question type:
<select ng-change="question.setChild()" ng-model="question.subClass">
<option value="slidingPuzzleQuestion">slidingPuzzleQuestion</option>
</select>
</div>
<div class="questionContainer">
<div class="puzzleContainer">
<input type="file" name="image" id="puzzleContainerImage" ng-file-select="question.child.imageFileSelected()">
</div>
</div>
AngularJS Model:
var scavengerHuntApp = angular.module('scavengerHuntApp', []);
scavengerHuntApp.controller('QuestionsCtrl', function ($scope) {
function ScavengerHunt() {
var self = this;
self.questions = [];
self.addQuestion = function(question) {
self.questions.push(question);
}
}
function Question() {
var self = this;
self.id = 0;
self.subClass = "slidingPuzzleQuestion";
self.child = "";
self.setChild = function() {
var type = self.subClass;
if(type == 'slidingPuzzleQuestion'){
self.child = new SlidingPuzzleQuestion();
}
}
}
function SlidingPuzzleQuestion() {
var self = this;
self.imageFileSelected = function () {
console.log()
};
}
//Utilities function
$scope.addEmptyQuestion = function() {
$scope.scavengerHunt.addQuestion(new Question());
}
$scope.scavengerHunt = new ScavengerHunt();
$scope.addEmptyQuestion();
});
AngularJS Directive
Up to now, I figured that I would probably have to use an AngularJS directive, since the ng-change does not work currently with input file (https://github.com/angular/angular.js/issues/1375). Hence, the following code does not work since in the html tag ng-file-select="question.child.imageFileSelected()"
, I have a context that is lost when trying to bind the element to a function.
scavengerHuntApp.directive("ngFileSelect",function(){
return {
link: function (scope, element, attrs) {
console.log(scope);
console.log(element);
var onChangeFunc = element.scope()[attrs.customOnChange];
element.bind('change', onChangeFunc);
}
}
});
So, is there a way to pass the current context in the html code to bind it to a particular object ?
I hope everything is clear enough, if not let me know and I'll clarify as much as possible !
Upvotes: 5
Views: 2501
Reputation: 783
Ok, have a look at this plunker: http://plnkr.co/edit/qPK6EmAkt39QoZFZ5Sa3?p=preview
I have removed some of your code just to let you understand what's going on low level.
You can use isolated scope with callback attribute binding using &
symbol.
What it does is it registers the expression in the attribute as a callable function inside the isolated scope of the directive.
The rules are:
You register isolated scope
scope : {
myAttr : "&"
}
You specify the attribute in the form
my-attr="object.objectMethod(param1, param2)"
Angular wraps the objectMethod
with the callable wrapper
When needed, you call the wrapper like this:
scope.myAttr({param1: "value", param2:"value"})
object.objectMethod
call with parameters specifiedUpvotes: 4