Accessing parent scope - angularjs

Within readingController -> checkRomanization when I try to increase questionNumber it seems to do so only within an isolated scope, i.e. create a copy, but not change the variable within the main controller.
Within conjugationController -> checkConjugation however, when I try to increase questionNumber it works, it increases the variable within the main controller scope, and this is reflected in the AngularJS Batarang Chrome plugin and also on the page where questionNumber is bound to an element.
var app = angular.module('Tutorials', ['functions', 'ui.utils', 'tutorials']).controller('main', function ($scope, $element, Position, Romanize) {
$scope.sectionNumber = Position.sectionNumber;
$scope.tutorialNumber = Position.tutorialNumber;
$scope.questionNumber = Position.questionNumber;
$scope.sections = sections;
$scope.currentMaterials = [];
$scope.usersRomanization = {text:""};
$scope.clickPause = clickPause;
$scope.readingController = function ($scope, Romanize){
$scope.currentMaterials = $scope.sections[$scope.sectionNumber].tutorials[$scope.tutorialNumber].material;
$scope.currentMaterial = $scope.currentMaterials[$scope.questionNumber];
$scope.getRomanization = function(Romanize){
Romanize.get($scope.currentMaterial).then(function(d){
$scope.romanized = d;
});
$scope.$apply();
};
$scope.getRomanization(Romanize);
$scope.$apply();
$scope.checkRomanization = function(){
if (!checkTime($scope)){return}
if ($scope.romanized === $scope.usersRomanization.text){
$scope.usersRomanization.text = '';
$scope.questionNumber++;
$scope.currentMaterial = $scope.currentMaterials[$scope.questionNumber];
$scope.getRomanization(Romanize);
$scope.$apply();
};
$scope.$apply();
}
}
$scope.conjugationController = function (){
var loadNewVerbs = function (scope) {
scope.currentMaterials = scope.sections[scope.sectionNumber].tutorials[scope.tutorialNumber].material;
if (scope.currentMaterials === undefined) {
alert("Out of new questions");
return
}
scope.verbs = conjugate(scope.currentMaterials[scope.questionNumber]);
scope.correct = scope.verbs.conjugations[0].text;
fisherYates(scope.verbs.conjugations);
scope.$apply();
};
loadNewVerbs($scope);
$scope.checkConjugation = function (answer) {
if (!checkTime($scope)){return}
answer.colorReveal = "reveal-color";
if (answer.text === $scope.correct) { //if correct skip to congratulations
$scope.questionNumber++;
setTimeout(function () {
loadNewVerbs($scope);
$scope.$apply();
}, 500);
};
};
};
To me this would indicate that the controllers were nested differently in the HTML, but they're not, they're siblings (controlled by an ng-switch on sectionNumber)
<body ng-controller="main">
<div id="sidebar_left"><div id="header"></div>
<ul id="nav" menu-accordion="header = 'section_title'">
<ul ng-repeat="section in sections">
<li class="section_title {{section.active}}" >
{{section.name}}
</li>
<ul>
<li class="tutorial_title {{tutorial.active}}" ng-click="loadFromMenu($parent.$index, $index)" ng-repeat="tutorial in section.tutorials">
{{tutorial.name}}
</li>
</ul>
</ul>
</ul>
<span class="question-number">{{questionNumber}}/{{currentMaterials.length}}</span>
</div>
<div id="container">
<video ng-click="clickPause()" poster="./poster.png" video-watcher class="video-js vjs-default-skin" id="myvideo" congrats="questionNumber" video-loader="currentTutorialName" id="video" controls>
<source type="video/mp4" src="{{currentTutorialName}}.mp4"></source>
<source type="video/webm" src="{{currentTutorialName}}.webm"></source>
Your browser does not support the video tag.
</video>
<br />
<button ng-click="replay()" id="reset">Replay</button>
<br />
<div ng-switch on="sectionNumber" id="panel">
<div ng-switch-when="0" ng-controller="readingController"><div id="base">{{currentMaterial}}</div><br />
<input placeholder="Enter text" ui-keyup="{13:'checkRomanization()'}" ng-model="usersRomanization.text"></input>
<button ng-click="checkRomanization()">Check</button>
</div>
<div ng-switch-when="1" ng-controller="conjugationController">
<div id="base">{{verbs.base}}</div>
<ul class="answers">
<li ng-click="checkConjugation(answer)" ng-repeat="answer in verbs.conjugations" class="{{answer.colorReveal}} answer {{answer.correct}}" id="answer{{$index}}">
{{answer.text}}
</li>
</ul>
</div>
</div>
<br />
<br />
<br />
<div class="message" >{{message}}</div>
</div>
</body>
So what the hell?

Related

two way binding not working even with dot notation

I'm starting with AngularJS and I am using a controller variable to navigate an array of questions, and it is working when using nextQuestion function, index gets updated and the next question is shown in the view, but if I try to obtain the same value (index) in a different function, it always returns 0.
I have seen on other questions that you should use an object to contain the variable to not manipulate primitive types directly in the controller, but it still does not work.
My controller:
myApp.controller('SurveyController',['$scope','$http', '$location','$routeParams','surveyMetrics','DataService',function($scope,$http, $location,$routeParams,surveyMetrics,DataService){
console.log('LOADED QUIZ CONTROLLER');
var vm = this;
vm.scope = {
index: 0
};
vm.surveyMetrics = surveyMetrics;
vm.surveyQuestions = DataService.surveyQuestions;
vm.DataService = DataService;
/*
vm.getQuestions = function(){
$http.get('/api/questions').then(function(response){
$scope.questions = response.data;
});
}
*/
/*
vm.activateSurvey = function(){
surveyMetrics.changeState(true);
}
*/
vm.getCurrentIndex = function(){
return vm.scope.index;
}
vm.nextQuestion = function () {
console.log('NEXT QUESTION!');
console.log('NUMBER OF QUESTIONS: '+ vm.surveyQuestions.length);
var currentIndex = vm.getCurrentIndex();
var newIndex = currentIndex+1;
scope = {};
if (currentIndex == vm.surveyQuestions.length) {
newIndex = vm.surveyQuestions.length -1;
}
vm.scope.index = newIndex;
console.log('Inside Object: '+vm.scope)
console.log('vm.index'+vm.scope.index);
console.log('vm.indexFunction'+vm.getCurrentIndex());
}
/*
vm.previousQuestion = function () {
console.log('PREVIOUS QUESTION!');
console.log('NUMBER OF QUESTIONS: '+ vm.surveyQuestions.length);
if (vm.scope.index == 0) {
vm.scope.index = 0;
}else{
vm.scope.index--;
}
}
*/
vm.activeSurveyQuestion = function(questionId,index){
console.log('question id and index',questionId,index);
if (questionId == index) {
var navBtn = document.getElementById('navBtn_'+index);
navBtn.classList.add('active');
}
}
vm.navigateSurvey = function () {
var answerPane = document.getElementById('answer-pane');
document.onkeydown = function (e) {
console.log('INSIDE KEYDOWN: ')
e.preventDefault();
var pressedKey = e.keyCode;
console.log('PRESSED KEY IN SURVEY: ' + pressedKey);
if (pressedKey === rightArrow) {
console.log('survey - right arrow pressed');
document.getElementById('nextQuestionBtn').click();
console.log('FUCKING INDEX FML!: '+vm.getCurrentIndex()+' | '+vm.scope.index);
var questionType = DataService.getQuestionType(vm.scope.index);
console.log('Survey Controller: question type: '+questionType);
}
if (pressedKey === leftArrow) {
console.log('survey - left arrow pressed');
document.getElementById('previousQuestionBtn').click();
}
(...)
My View:
<!--Satisfaction Survey-->
<div ng-controller="SurveyController as survey" ng-init="survey.getSurvey();">
<!--
<p ng-repeat="question in survey.surveyQuestions" ng-show ="survey.surveyMetrics.surveyActive">
{{question.question}}
</p>
-->
<!--Survey Modal -->
<div class="modal fade" id="surveyModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="text-center"> Customer Satisfaction Survey</div>
<div class="modal-header">
<h4 class="modal-title">{{survey.surveyQuestions[survey.getCurrentIndex()].question}}</h4>
</div>
<div class="modal-body survey" id="answer-pane">
<div class="row">
<div class="col-sm-2 survey-left-arrow" ng-click="survey.previousQuestion();" id="previousQuestionBtn">
<p>‹</p>
</div>
<div class="col-sm-8">
<!-- <p ng-repeat="answer in survey.surveyQuestions[survey.index].answers">{{answer}}</p> -->
<p ng-repeat="answer in survey.surveyQuestions[survey.getCurrentIndex()].answers">
<button type="button" class="btn" id="answerId_{{survey.getCurrentIndex()}}"
ng-class="{'survey-check-box': (survey.surveyQuestions[survey.getCurrentIndex()].type !== 'SingleChoice'),
'survey-btn_{{($index+1)}}': (survey.surveyQuestions[survey.getCurrentIndex()].type === 'SingleChoice')}">
<input type="checkbox" ng-if="survey.surveyQuestions[survey.getCurrentIndex()].type !== 'SingleChoice'"> {{answer}}
</button>
</p>
</div>
<div class="col-sm-2 survey-right-arrow " ng-click="survey.nextQuestion();" id="nextQuestionBtn">
<p>›</p>
</div>
</div>
</div>
<div class="text-center">
<strong> <p>Question: {{survey.surveyQuestions[survey.scope.index].questionNum}} of {{survey.surveyQuestions.length}}</p> </strong>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
<!-- <nav aria-label="Survey navigation">
<ul class="pagination pagination-sm justify-content-center">
<div ng-repeat="question in survey.surveyQuestions" >
<li class="page-item">
<a class="page-link" id = "navBtn_$index" ng-click="survey.index = $index">{{question.id}}</a>
</li>
</div>
</ul>
</nav> -->
</div>
</div>
I would like for the controller to change the variable and the view to update accordingly
Thank you for your time and thank you in advance.
It's 'survey.scope.index' not 'survey.index' in your HTML. I think you may be unclear the difference between using 'this' and '$scope'. You're mixing the two together which is not necessary. I would suggest removing 'scope' and just reference it in your HTML as 'survey.index'.

I don't get out of the function Angularjs

I have a simple Angular code to show and hide a poppin, but every time I use it I am blocked in the function.
In my controller I have this to show the poppin :
$scope.showHidden = function() {
console.log('in')
$scope.showIt = true;
};
And this to hide it :
$scope.hideIt = function() {
console.log('out')
$scope.showIt = false;
};
And in my HTML :
<li class="beer_list_item beer_item" ng-repeat="beer in beers | filter : myFilter" ng-click="showHidden()">
<img ng-src="{{beer.img}} " alt="{{beer.alt}}" />
<div class="beer_list_item_desc" ng-show="showIt">
<h2 class="title1">{{beer.name}}</h2>
<img src="{{beer.img}}" alt="{{beer.alt}}"/>
<p>{{beer.desc}}</p>
<button class="btn" ng-click="hideIt()">Close</button>
</div>
</li>
If I click on the item the poppin appears, and when I click on the close btn, I see 'out' and 'in' in my logs, and the poppin never disappear.
I'm sure it's a stupid mistake, but I don't see it. If anyone have an idea.. thanks by advance !
You need to prevent the event propagation when click on hideIt:
<button class="btn" ng-click="hideIt();$event.stopPropagation();">Close</button>
This could be a refactoring:
function BeersCtrl($scope, beers) {
$scope.beers = beers;
$scope.showBeerList = true;
$scope.toggleBeerList = function(event) {
$scope.showBeerList = !$scope.showBeerList;
};
}
angular
.module('test', [])
.controller('BeersCtrl', BeersCtrl)
.value('beers', [
{ name: 'Peroni' },
{ name: 'Guinnes' }
])
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<section ng-app="test">
<article ng-controller="BeersCtrl">
<div>
<button
ng-click="toggleBeerList($event)"
type="button">Toggle Beer List</beer>
</div>
<ul ng-show="showBeerList">
<li
ng-repeat="beer in beers">
<span ng-bind="beer.name"></span>
</li>
</ul>
</article>
</section>

ng-repeat is not working. Think there is a scope issue but not sure.

So I have the following div:
<div id="chatrooms" ng-controller="TableMsgController">
<section id="chatroom">
<div id="messages" >
<ul>
<li ng-repeat="entry in seenMsgs">{{entry.msg}}</li>
</ul>
</div>
<form action="">
<input type="text" id="userMsg" ng-model="userMsg">
<input type="button" class="gButton" id= "sendMsgBtn" value="Send" ng-click="sendMsg()" />
</form>
</section>
</div>
And I have the following controller:
tables.controller('TableMsgController',function ($rootScope,$scope) {
$scope.msgSeen = [];
$scope.sendMsg = function () {
//console.log("sendMsg button pushed");
//console.log($scope.userMsg);
$scope.msgSeen.push( {'msg':$scope.userMsg} );
// console.log($scope.msgSeen);
};
The ng-repeat is not working.
Any idea why?
Z
Two things I can spot:
a) You're missing a closing brace on sendMsg:
tables.controller('TableMsgController',function ($rootScope,$scope) {
$scope.msgSeen = [];
$scope.sendMsg = function () {
//console.log("sendMsg button pushed");
//console.log($scope.userMsg);
$scope.msgSeen.push( {'msg':$scope.userMsg} );
// console.log($scope.msgSeen);
} <---------------------------------------------- :)
};
and b) you define msgSeen in the scope but are attempting to iterate over seenMsgs:
<li ng-repeat="entry in seenMsgs">{{entry.msg}}</li>
Resolve both of these and see if that fixes it.

`ng-click` not calling the controller function some times

I have 2 popup's which is controller by a service in a page. on click on the div element i am calling the controller function. after i added the 2nd popup directive especially some times the ng-click not working properly. how to solve this?
here is my service.js
"use strict";
angular.module("tcpApp").service("modalService", function ( $rootScope) {
//header configuration
$rootScope.hideModal = function() {
$rootScope.showModal = false;
};
this.changePass = function ( configId ) {
$rootScope.showModal = true; //this is for global
$rootScope.currentConfigPopView = 'views/tools/'+configId+'.html';
$rootScope.$apply();
};
this.showSummary = function () {
this.showSummaryPop = true;
}
this.hideSummary = function () {
this.showSummaryPop = false; //this is within controller
}
});
html:
<div class="statusBoard board8" ng-click='modal.showSummary("board8")'>
<span><img src="../images/iconDetails.png" alt="icon plan and actual"></span>
<h2>{{boardAssets.board8.title}}</h2>
<span class="row dwo">
<span class="catg">Total Issue Reported</span>
<span class="cd issueData">{{contractor.IssueDetails.TotalIssue}}</span>
</span>
<span class="row mas">
<span class="catg">Issue Resolved</span>
<span class="cd resolveData">{{contractor.IssueDetails.IssueResolved}}</span>
</span>
<span class="row rfi">
<span class="catg">Issue Remaining</span>
<span class="cd remainData">{{contractor.IssueDetails.IssueRemaining}}</span>
</span>
</div>
<body-footer></body-footer>
<config-popup></config-popup> //after i added this directive getting ng-click issue.
<modal-popup></modal-popup>
config popup html:
<div class='ng-modal' ng-if="showModal">
<div class='ng-modal-overlay' ng-click='hideModal()'></div>
<div class='ng-modal-dialog' ng-style='dialogStyle'>
<div class='ng-modal-dialog-content'>
<ng-include src="currentConfigPopView"></ng-include>
</div>
</div>
</div>

Why does my function in my custom directive trigger twice upon re-entering a screen?

I have a custom directive that returns various template files to build survey questions based on their type (select, checkbox etc) but the behaviour of my directive changes based on whether I have already accessed it despite having completely left the url and hopefully destroyed any remnant of it.
Basically changeDate is supposed to run once upon entering the directive (triggered by the setting of tempdate) which should update a label on the template. This actual input element is being hidden. The problem is that if I leave the page that uses this template completely and then go back into it the changeDate function runs twice regardless of what is inside it or what it does.
datepicker.html
<div class="question-title q-element"><div>{{question.question[language]}}</div></div>
<div class="question-response">
<ng-form name="innerForm">
<span>
<span ng-show="question.response" class="select-label-pos">{{formattedDate}}</span>
<span ng-show="!question.response" class="select-label-pos">Pick a Date</span>
</span>
<input ng-change="changeDate()" ng-required="{{question.mandatory}}" ng-model="tempdate" type="date">
</ng-form>
</div>
inputDirective.js
(function(){
"use strict";
angular.module('gather.directives.inputDirective',
[
]).directive('inputDirective',
[
function(){
return {
link: function(scope, element, attrs){
scope.language = attrs.language;
if(attrs.inputDirective==="datepicker"){
var first = true;
if(attrs.draft==='false') {
//console.log('not a draft, setting default date');
scope.tempdate = new Date(1999, 3, 3);
}else{
scope.tempdate = new Date(scope.question.response);
//console.log('got a draft, getting response date');
}
console.log('Running Datepicker, the response is ', scope.question.response);
scope.logOut = function(){
console.log('BUILDING TEMPLATE');
console.log(scope.question.qid);
};
scope.changeDate = function(){
// console.log('first: ',first);
//console.log('attrs.draft: ', attrs.draft);
if(first===true&&attrs.draft==='false'){
//if its the first time and not a draft just flip the switch
first = false;
//console.log('Not a draft, first load/change: Just flip the switch');
//console.log(scope.question);
}else if(attrs.draft==='true'){
//if draft is true we will already have a value, set the tempdate abd update the label
attrs.draft = 'false';
first = false;
var d = new Date(scope.question.response);
scope.day = d.getDate();
scope.month = d.getMonth()+1;
scope.year = d.getFullYear();
scope.formattedDate = scope.month + '-'+scope.day+'-'+scope.year;
//console.log('Survey is a draft: Update the datepicker label with the response');
} else{
//if its not the first time and draft is false we start normal updates of the values
var d = new Date(scope.tempdate);
scope.day = d.getDate();
scope.month = d.getMonth()+1;
scope.year = d.getFullYear();
scope.formattedDate = scope.month + '-'+scope.day+'-'+scope.year;
scope.question.response = scope.tempdate;
//console.log('Not a draft, not first change/load: Update the datepicker label with the response');
}
};
}
},
templateUrl: function(elem, attrs, scope){
console.log();
return "views/question-types/"+attrs.inputDirective+"-question.html";
},
};
}]
);
survey.html
<a id="top"></a>
<div id="survey" class="snap-container">
<div id="header">
<h1>Capture Data </h1>
<a href="#/home">
<div class="home-button">
</div>
</a>
<div class="menu-button" snap-toggle="right">
</div>
</div>
<div class="surveys-container">
<div id="template" ng-repeat="asset in template | filter:{type:'html'}">
<ng-include src="addAssetPath(asset.path)"></ng-include>
</div>
<div ng-show="currentGroup == false" class="groupMenu overlay-view">
<h2 class="group-title">Lead Capture</h2>
<div ng-repeat="group in survey.groups|orderBy:'group_order'" >
<div ng-click="changeGroup(group.group_name.en)" class=" menu-group-title">
<span>{{group.group_name.en}}</span>
<span ng-if="group.group_name.en != 'Barcode'" class="arrow-icon ui-icon"></span>
<span ng-if="group.group_name.en == 'Barcode'" class="scan-icon ui-icon"></span>
</div>
</div>
<button class="action-button client-gradient-submit" ng-click="submitForm()">Submit</button>
<button class="action-button client-gradient-draft" ng-click="saveDraft()">Save</button>
</div>
<div ng-show="currentGroup == group.group_name.en" class="group group-container overlay-view" ng-repeat="group in survey.groups|orderBy:'group_order'">
{{logTest(group.group_name.en, $index)}}
<h2 class="group-title">{{group.group_name.en}}</h2>
<div class=" question-container {{question.css_class.en}}" ng-repeat="question in group.questions|orderBy:'question_order'">
<div class="" ng-switch="question.type">
<div input-directive="text" question="question" language="{{surveyLang}}" draft="{{draft}}" ng-switch-when="S">
</div>
<div input-directive="select" question="question" language="{{surveyLang}}" draft="{{draft}}" ng-switch-when="!">
</div>
<div input-directive="radio" question="question" language="{{surveyLang}}" draft="{{draft}}" ng-switch-when="L">
</div>
<div input-directive="textarea" question="question" language="{{surveyLang}}" draft="{{draft}}" ng-switch-when="T">
</div>
<div input-directive="checkbox" question="question" language="{{surveyLang}}" draft="{{draft}}" ng-switch-when="M">
</div>
<div input-directive="datepicker" question="question" language="{{surveyLang}}" draft="{{draft}}" ng-switch-when="D">
</div>
<div input-directive="other" question="question" language="{{surveyLang}}" draft="{{draft}}" ng-switch-default>
</div>
</div>
</div>
<button class="done-button" ng-click="changeGroup(false)" ng-show="currentGroup != false">Done</button>
</div>
</div>
</div>

Resources