I am working on a game made with angularjs. I have one problem that I haven't been able to solve yet. I would like to use a popup dialog ( no alert ) whose content depends on the context. This popup contains a button, that when clicked starts the game.
Since the content is dynamic the ng-click function does not work.
I've tried with directives and straight from the controller but have not gotten it to work.
My concrete question is how do I add HTML Button to a with angularjs that contains a ng-click function that will actually fire?
Edit: here one attempt (that actually gets the button to show, but ng-click does nothing): Controller:
{
if ($scope.quiz.state === 'finished' || $scope.quiz.state === 'initialized') {
var startButton = '<br><br><button data-ng-click="startQuiz">start quiz</button>';
$scope.popupText = $sce.trustAsHtml('Stating ' + quiz.name + startButton);
$scope.showStart = false;
$scope.showPopup = true;
}
};
$scope.startQuiz = function() {
$scope.showPopup = false;
if ($scope.quiz.state === 'initialized') {
$scope.quiz.start();
$scope.quizTimer.start($scope, $timeout);
}
};
Html:
<div id="popupBox">
<div id="closePopup" data-ng-click="closePopup()">X</div>
<div data-ng-bind-html="popupText"></div>
</div>
I am working on a game made with angularjs. I have one problem that I haven't been able to solve yet. I would like to use a popup dialog ( no alert ) whose content depends on the context. This popup contains a button, that when clicked starts the game.
Since the content is dynamic the ng-click function does not work.
I've tried with directives and straight from the controller but have not gotten it to work.
My concrete question is how do I add HTML Button to a with angularjs that contains a ng-click function that will actually fire?
Edit: here one attempt (that actually gets the button to show, but ng-click does nothing): Controller:
{
if ($scope.quiz.state === 'finished' || $scope.quiz.state === 'initialized') {
var startButton = '<br><br><button data-ng-click="startQuiz">start quiz</button>';
$scope.popupText = $sce.trustAsHtml('Stating ' + quiz.name + startButton);
$scope.showStart = false;
$scope.showPopup = true;
}
};
$scope.startQuiz = function() {
$scope.showPopup = false;
if ($scope.quiz.state === 'initialized') {
$scope.quiz.start();
$scope.quizTimer.start($scope, $timeout);
}
};
Html:
<div id="popupBox">
<div id="closePopup" data-ng-click="closePopup()">X</div>
<div data-ng-bind-html="popupText"></div>
</div>
Share
Improve this question
edited Dec 29, 2013 at 13:04
BenMorel
36.6k51 gold badges205 silver badges335 bronze badges
asked Nov 26, 2013 at 22:43
cw24cw24
1,7332 gold badges22 silver badges31 bronze badges
4
- we can't guess how you are trying to do this without seeing some code – charlietfl Commented Nov 26, 2013 at 22:54
- I would think you would want to do something like ng-click="$rootscope.broadcast(event, data)". Have whatever controller starts your game listening for the event. – Zack Argyle Commented Nov 26, 2013 at 23:19
- You should mark your own answer as the correct one in order to make clear that the problem is solved. you can upvote other helpful answers apart from that. – lex82 Commented Nov 27, 2013 at 22:48
- I purposely haven't marked my answer as correct yet, because I am not convinced that it is the best. I am waiting for feedback. – cw24 Commented Nov 28, 2013 at 7:58
3 Answers
Reset to default 4Using the help from the other answers I got it to work by doing the following (this is probably not the best way, but it works. Please ment if there is someway to improve this.):
Controller:
...
$scope.piledStartPopupText = $pile(angular.element('<br><br><button data-ng-click="startQuiz()">start quiz</button>'))($scope);
$scope.popupText = 'Starting ' + $scope.quiz.name;
$scope.getCompiledStartPopupText = function() {
return $scope.piledStartPopupText;
};
$scope.openStartQuizPopup = function()
{
if ($scope.quiz.state === 'finished' || $scope.quiz.state === 'initialized') {
if($scope.quiz.state === 'finished') {
$scope.quiz.reinitialize();
}
$scope.showPopup = true;
}
};
$scope.closePopup = function() {
$scope.showPopup = false;
if($scope.quiz.state !== 'started') {
$scope.showStart = true;
}
};
$scope.startQuiz = function() {
$scope.showStart = false;
$scope.showPopup = false;
if ($scope.quiz.state === 'initialized') {
$scope.quiz.start();
$scope.quizTimer.start($scope, $timeout);
} else if ($scope.quiz.state === 'finished') {
$scope.quiz.restart();
$scope.quizTimer.restart($scope, $timeout);
}
};
$scope.endGame = function()
{
$scope.quiz.state = 'finished';
$scope.showPopup = true;
$scope.showStart = true;
};
...
Directive:
directive('popUp', function() {
return {
restrict: 'A',
link: function($scope, elm, attrs) {
$scope.$watch('quiz.state', function(value){
if(value === 'finished') {
elm.html('finished');
} else {
var piledStartButton = $scope.getCompiledStartPopupText();
elm.html($scope.popupText);
elm.append(piledStartButton);
}
});
}
};
};
HTML:
<div id="popup" ng-show="showPopup">
<div id="popupBox">
<div id="closePopup" data-ng-click="closePopup()">X</div>
<div data-pop-up class="cta"></div>
</div>
</div>
If you are trying to call closePopup()
, let's say your app is initialized at the top of the html and you have a ng-controller="MsgCtrl"
as well, within the controller have your code
<div id="popupBox">
<div id="closePopup" data-ng-click="closePopup()">X</div>
<div data-ng-bind-html="popupText"></div>
</div>
and then in the script of your app, write something like this
function MsgCtrl($scope) {
$scope.closePopup = function () {
console.log("function called");
};
}
Look at this for a similar example and experiment with it.
By using the $pile service, you can evaluate arbitrary HTML in the context of a certain scope. Example:
var element = $pile(angular.element('<button ng-click="doSomething()"></button>'))(scope);
The variable element
then contains an angular.element (or jQuery if you are using it) that you can insert anywhere in the DOM. Clicking the button will result in an invocation of scope.doSomething()
. Hope this helps.