how to implement ng-show right way? - angularjs

can someone check my code and tell me how to make it in right way?
it works but i don't think this is the right
if i would have 20 sub menus,i would need to create 20 functions,which is definitely wrong
thank you in advance
<ul class="menu-top">
<li ng-click="menu2show()">drinks</li>
<li ng-click="menu1show()">food</li>
<li ng-click="menu3show()">desserts</li>
</ul>
<div id="menu-content" ng-controller="MenuCtrl">
<div class="menu1" ng-show="show1" >
<div class="item" ng-repeat="item in menu.menu1">
</div>
</div>
<div class="menu2" ng-show="show2" >
<div class="item" ng-repeat="item in menu.menu2">
</div>
</div>
<div class="menu3" ng-show="show3" >
<div class="item" ng-repeat="item in menu.menu3">
</ul>
</div>
</div>
</div>
var app = angular.module('App', []);
app.controller('MenuCtrl', function($scope) {
$scope.menu = {
menu1:[
{"name":"item1", "price":"1", "desc":"aaa"},
{"name":"item2", "price":"2", "desc":"bbb"},
{"name":"item3", "price":"3", "desc":"ccc"},
],
menu2:[
{"name":"item8", "price":"6", "desc":"zzz"},
{"name":"item9", "price":"4", "desc":"xxx"},
{"name":"item10", "price":"2", "desc":"sss"},
],
menu3:[
{"name":"item15", "price":"3", "desc":"mmmm"},
{"name":"item16", "price":"1", "desc":"nnn"},
{"name":"item17", "price":"5", "desc":"bbb"},
]};
$scope.show1 = true;
$scope.menu1show = function(){
$scope.show1 = true;
$scope.show2 = false;
$scope.show3 = false;
}
$scope.menu2show = function(){
$scope.show1 = false;
$scope.show2 = true ;
$scope.show3 = false;
}
$scope.menu3show = function(){
$scope.show1 = false ;
$scope.show2 = false ;
$scope.show3 = true ;
}
});

You can make a scope variable to capture the menu that you wish to display.
$scope.showMenu = 1;
Then for each menu:
<div class="menu2" ng-show="showMenu === 2" >
...
<div class="menu1" ng-show="showMenu === 1" >
and so on.
And for the click:
<li ng-click="showMenu = 2">drinks</li>
and so on.

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'.

How to make unique ng-model in ng-repeat

I want to make each test(ng-model) like test1, test2 unique in below code..
<div ng-repeat="item in Array">
<div>{{item.Name}}</div>
<a ng-click="openClose(test)>show/hide</a>
<div ng-show="test">{{item.Des}}</div>
</div>
$scope.openClose = function (modalName) {
$scope[modalName] = $scope[modalName] ? false : true;
}
You can maintain the show / hide using the $index value you get for each element when you use ng-repeat.
angular.module('app',[]).controller('mainCtrl', function($scope){
$scope.Array = [{Name:'abc'},{Name:'zzz'},{Name:'yyy'},{Name:'xxx'}];
$scope.openClose = function (index) {
if($scope.selectedValue == index){
$scope.selectedValue = -1;
}else{
$scope.selectedValue = index;
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller='mainCtrl'>
<div ng-repeat="item in Array">
<div>{{item.Name}}</div>
<a ng-click="openClose($index)">show/hide</a>
<div ng-show='$index === selectedValue'>Hide Show content</div>
</div>
</div>

How to work on ng-show for particular index in ng-repeat

HTML:
<div class="displayImgData col-sm-3" ng-repeat="item in profileData" >
<a ng-show="onLoadFav" title="Make as Favourite">
<img class="styleright" src="assets/images/unfavourite.png" ng-if="(item.favourite ==0)" ng-click="favouriteUser(item.userid);">
</a>
<a ng-show="onLoadUnFav" title="Favourite">
<img class="styleright" src="assets/images/favourite.png" ng-if="(item.favourite ==1)" ng-click="unfavouriteUser(item.userid);" >`
</a>`
<a ng-show="newFav" title="Make as Favourite">
<img class="styleright" src="assets/images/unfavourite.png" ng-click="favouriteUser(item.userid);">
</a>
<a ng-show="newUnFav" title="Favourite">
<img class="styleright" src="assets/images/favourite.png" ng-click="unfavouriteUser(item.userid);" >
</a>
</div>
JS:
$scope.onLoad = function(){
$scope.profileData = [{'favourite':0,'userid':1},{'favourite':0,'userid':2},{'favourite':1,'userid':3}]
};
$scope.onLoadFav = false;
$scope.onLoadUnFav = false;
$scope.newFav = false;
$scope.newUnFav = true;
$scope.unfavouriteUser= function(){
UserService.getSocialMedia(json).then(function (res) {
if(res.statuscode == 0){
$scope.onLoadFav = false;
$scope.onLoadUnFav = false;
$scope.newFav = false;
$scope.newUnFav = true;
}
});
};
I have onload()which I call on loading my page, I will make my favourite.png enabled if item.favourite == 1in my $scope.profileData and unfavourite.png enabled if item.favourite == 0. If I want to make a particular record alone unfavourite . I am using unfavourite() and I get response from backend as success . If i call onload() again it will be like reloading entire page again.So I given ng-show = onLoadFav ,onLoadUnFav, newFav, newUnFavrespectively in html to make it icon enabled accordingly., But the problem is , since it in ng-repeat all the icon is becoming enabled or disabled , not the particular one. How to work on ng-show for particular index in ng-repeat
I did not test the code, will do it soon. but you could use an array addressed by userid
<div class="container" ng-app="confusionApp">
<div class="displayImgData col-sm-3" ng-controller="testCtrl" ng-repeat="item in profileData" >
<a ng-show="loadData[item.userid].onLoadFav" title="Make as Favourite">
<img class="styleright" src="assets/images/unfavourite.png" ng-if="(item.favourite ==0)" ng-click="favouriteUser(item.userid);">
</a>
<a ng-show="loadData[item.userid].onLoadUnFav" title="Favourite">
<img class="styleright" src="assets/images/favourite.png" ng-if="(item.favourite ==1)" ng-click="unfavouriteUser(item.userid);" >`
</a>`
<a ng-show="loadData[item.userid].newFav" title="Make as Favourite">
<img class="styleright" src="assets/images/unfavourite.png" ng-click="favouriteUser(item.userid);">
</a>
<a ng-show="loadData[item.userid].newUnFav" title="Favourite">
<img class="styleright" src="assets/images/favourite.png" ng-click="unfavouriteUser(item.userid);" >
</a>
</div>
</div>
And that would be the controller
angular.module('testApp',[])
.controller('testCtrl',['$scope', function($scope) {
$scope.loadData = [];
$scope.onLoad = function(){
$scope.profileData = [{'favourite':0,'userid':1},{'favourite':0,'userid':2},{'favourite':1,'userid':3}];
for (var i=0; i < $scope.profileData.length; i ++ ) {
$scope.loadData[$scope.profileData[i].userid] = {onLoadFav : false, onLoadUnFav : false, newFav: false, newUnFav : true};
}
};
$scope.unfavouriteUser= function(pUserID){
UserService.getSocialMedia(json).then(function (res) {
if(res.statuscode == 0){
$scope.loadData[pUserID].onLoadFav = false;
$scope.loadData[pUserID].onLoadUnFav = false;
$scope.loadData[pUserID].newFav = false;
$scope.loadData[pUserID].newUnFav = true;
}
});
};
$scope.onLoad();
}]);

Accessing parent scope

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?

trying to use ngSwitch in angular

I'm testing the following code in angular and it's not working. I'm very new to Angular and I've been unable to figure this out. All I'm trying to do is show a particular element based on a step number when next/back buttons are clicked.
<div ng-app ng-controller="Ctrl">
<div ng-switch on="selection" >
<div ng-switch-when="2" step-number="2">Settings Div</div>
<span ng-switch-when="1" step-number="1">Home Span</span>
<span ng-switch-default step-number="3">default</span>
<button ng-click="back(step-number)">back</button>
<button ng-click="forward(step-number)">forward</button>
</div>
</div>
function Ctrl($scope) {
$scope.items = ['1', '2', '3'];
$scope.forward = function($selected) { $scope.selection = $scope.items[$selected - 1]; };
$scope.back = function($selected) { $scope.selection = $scope.items[$selected - 1]; };
}
I think I would refactor what you are doing to the following:
Demo: http://plnkr.co/edit/b7mQ5ssSqECDUhvN0S2b?p=preview (click back first).
app.controller('Ctrl', function($scope) {
$scope.name = 'World';
$scope.selection = 2;
$scope.items = ['div 1', 'div 2', 'div 3'];
$scope.forward = function() {
if ($scope.selection==$scope.items.length-1) $scope.selection=0;
else $scope.selection++;
};
$scope.back = function() {
if ($scope.selection==0) $scope.selection = $scope.items.length-1;
else $scope.selection --;
};
});
<body ng-controller="Ctrl">
<div >
<div>
<div>{{items[selection]}}</div>
<button ng-click="back()">back</button>
<button ng-click="forward()">forward</button>
</div>
</div>
</body>
I'm not sure what you are trying to do with step-number, but here is a way to make your buttons work between the values of 1 and 3 inclusive:
<div ng-switch on="selection">
<div ng-switch-when="2">Settings Div</div>
<span ng-switch-when="1">Home Span</span>
<span ng-switch-default step-number="3">default</span>
<button ng-click="back()">back</button>
<button ng-click="forward()">forward</button>
</div>
function MyCtrl($scope) {
$scope.selection = 3;
$scope.forward = function () {
$scope.selection += 1;
if ($scope.selection > 3) $scope.selection = 3;
console.log($scope.selection);
};
$scope.back = function () {
$scope.selection -= 1;
if ($scope.selection < 1) $scope.selection = 1;
console.log($scope.selection);
};
}
fiddle

Resources