Angular ng-show is not showing the element in the view - angularjs

I am trying to implement a simple Angular ng-show in my code but I cannot seem to make it work. I am attaching the code below.
HTML
<div ng-repeat="question in data.questions track by $index" ng-if="question.visible" class="slide">
<md-radio-group ng-model="question.selectedAnswer" ng-if="vm.showSliderChecker">
<md-radio-button ng-repeat="ans in question.answer track by $index" ng-value="ans._id"
ng-click="radioBtnClick({qId: question._id, ansId: ans._id})">{{::ans.description}}
</md-radio-button>
</md-radio-group>
<div class="wrapper" ng-show="vm.showSliderChecker">
<div class="toggle_radio">
<input type="radio" class="toggle_option" id="first_toggle" name="toggle_option" >
<label for="first_toggle" class="widthEighth" ng-repeat="ans in question.answer track by $index" ng-value="ans._id"
ng-click="radioBtnClick({qId: question._id, ansId: ans._id}); showSliderClickedMessage()"><p> {{$index+1}} </p></label>
</div>
</div>
</div>
Angular Controller
vm.checkSliderForDisplay = checkSliderForDisplay;
function initController(){
checkSliderForDisplay();
}
function checkSliderForDisplay() {
if($stateParams.testType === "Stress_management"){
vm.showSliderChecker = true;
console.log("The value of slider checker is true and here's proof ----> ");
console.log(vm.showSliderChecker);
}
else{
vm.showSliderChecker = false;
console.log("Alas, the slider checker is just a lot of false advertising and nothing more.");
console.log(vm.showSliderChecker);
}
}
initController();
Now here's the problem:
The console logs are showing on the console but the both the divs stay hidden. I have looked for a solution on this website and tried a bunch of combinations thinking I am missing some minute detail but I just can seem to make it work.

As you are using the Controller As synstax vm is the name you can refer to the controller in the scope.
If your code is running in a different closure, like from the controller constructor, you may need to refer to it differently.
Looks like that piece of code is called in the Controller constructor so "vm" won't be a defined variable there. You should use "this" instead:
function checkSliderForDisplay() {
if(this.testType === "Stress_management"){
this.showSliderChecker = true;
console.log("The value of slider checker is true and here's proof ----> ");
console.log(this.showSliderChecker);
}
else{
this.showSliderChecker = false;
console.log("Alas, the slider checker is just a lot of false advertising and nothing more.");
console.log(this.showSliderChecker);
}
}
If you add "use strict"; at the top of your js files you should get some warning.

Related

Deep watch on array not working in AngularJS data binding

I am using the popover directive from AngularStrap. I have a colleciton of objects that get rendered as toggles. When the toggles are clickedthe data on the scope is not changed... I've tried loads of different ways of doing this.
This is the controller of the popover
app.controller('CurvesPopoverCtrl', ['$scope', '$filter', 'AppData',
function($scope, $filter, AppData) {
'use strict';
$scope.popoverCurrencies = AppData.getCurrencies();
$scope.$watch ('popoverCurrencies', function(val) {
if(val !== null && val !== undefined){ // only fires when popover opens.
console.log("toggled", val);
//AppData.setCurrencies($scope.currencies);
}
}, true); // deep watch
}
]);
This is the template of the popover
<div class="well curves-popover" ng-controller="CurvesPopoverCtrl">
<div class="row">
<div ng-repeat="currency in popoverCurrencies">
<div class="clearfix" ng-if="$index % 3 == 0"></div>
<div class="col-md-4">
<div class="togglebutton">
<label>
<span ng-class="currency.iconClass"></span> <span>{{currency.ccy}}</span>
<input type="checkbox" checked="currency.build">
</label>
</div>
</div>
</div>
</div>
</div>
It gets a little complicated when you're attempting to watch a collection while using ng-repeat. According to the docs:
Each template instance gets its own scope ...
Therefore, the watch is not notified when the values within these other scopes are updated. One workaround is to bind a separate controller to each of the iterations of ng-repeat, as seen here. But another, possibly cleaner, approach is to utilize the ng-change directive to intercept the updating of these values. I explained it a bit here.

Set ons-switch with predifined values from Angular controller

I cannot seem to get the correct way to set the 'checked' attribute in ons-switch. This is so that I can setup user configurations page with pre-checked select boxes.
The Docs:
This is a checked switch but how do I set this using a variable in an angular controller?
For example, if ons-switch has a syntax like
I could have done:
I cannot seem to set attribute "checked" with no value in angular, as needed in the docs. I'm also unable to access the variable since it is part of an array of configurations.
Code Example:
controller:
var categInfo = [{Interest:'Classic', isChecked:true}, {Interest:'New', isChecked:false}];
html:
<ons-list-item ng-repeat="interest in categInfo" >
<span style="color: #666">{{interest.Interest}}</span>
<ons-switch modifier="list-item" var="{{interest.Interest}}" checked="{{interest.isChecked}}"></ons-switch>
</ons-list-item>
So what I want is that the html should show buttons that are checked/unchecked depending on interest.isChecked is true or false.
First of all, you need to bind the switch with ng-model, this will allow you to manage the ons-switch behavior directly from the controller. Setting the variable true or false, inside the controller, will automatically change the value of the state of the switch, same thing if you change the state from the switch (AngularJS binding).
If you want to check the status of the switch, you need to check the model value.
Here is a CodePen example. and the relative code.
HTML
<div ng-controller="MyController">
<ons-switch ng-model="switch"></ons-switch>
<ons-button ng-click="changeSwitch()">Change switch status</ons-button>
</div>
Controller
ons.bootstrap()
.controller('MyController', function ($scope) {
$scope.changeSwitch = function() {
$scope.switch = !$scope.switch;
if($scope.switch)
alert('checked');
else
alert('unchecked');
};
});
EDIT: SWITCH ARRAY EXAMPLE
Due to an Onsen UI bug about the initialization of the ons-switch element, I suggest you to use the following code to implement your switch.
<label class="switch">
<input type="checkbox" class="switch__input" checked>
<div class="switch__toggle"></div>
</label>
The appearance will be the same as the ons-switch element. This bug will be fixed in Onsen UI 1.4 release, so you can start using again the switch element after its release.
For what concerns the behavior of an array of switches, it's analog of the single switch. You still need to use 'ng-model' to bind the status of the switch. You are using ng-repeat to display the switch elements so, by using ng-model="item.isChecked", every element will be binded with the relative isChecked value inside the array. Here you can find a working CodePen example, and this is the relative code:
HTML
<div ng-controller="MyController">
<h2>What I am trying</h2>
<div ng-repeat="item in categInfo">
<div>This button should be {{item.isChecked}}</div>
<label class="switch">
<input ng-model="item.isChecked" type="checkbox" class="switch__input" checked>
<div class="switch__toggle"></div>
</label>
</div>
</div>
Controller
ons.bootstrap()
.controller('MyController', function ($scope, $timeout) {
//Need to go through the array and set as checked or not
$scope.categInfo = [{Interest:'Classic', isChecked:true}, {Interest:'New', isChecked:false}];
});

ng-init fetches value only once, even if the model value changes

I have a status filed deep nested to 3 levels in my model, I want to apply different classes to a div based on the value of the status. In order the save the typing and keep the html tidy, I wanted to apply short name to this status so I used ng-init to copy the values and use ng-class on ng-init variable. But ng-init gets its value only once, when I change the status again in controller it doesnt change but holds the old value. Is there a way to give short names to response.obj1.obj2.status at least inside a div?
<div ng-app="app">
<div ng-controller="statusCtrl">
<button ng-click="toggle()">toggle</button>
<div id="section1" ng-init="s1Status=response.section1.status">
<div id="statusIndicator" ng-class="{'success':s1Status==0,'error':s1Status==1}">Status</div>
</div>
<span>{{response.section1.status}}</span>
</div>
var app = angular.module('app', [])
app.controller('statusCtrl', function ($scope) {
$scope.response = {
section1: {
status: 1
}
};
$scope.toggle = function () {
if ($scope.response.section1.status === 0) $scope.response.section1.status = 1;
else $scope.response.section1.status = 0;
}
});
Demo: http://plnkr.co/edit/ES7rgf97BPFAWzkfIEhw?p=preview
EDIT:
Knockout JS has nice way to do this, where you can bind a model at any level to a div and any models referred inside that div will work with the parnet model as context. Thats what I'm looking for.
<div id="section1" data-bind="response.section1">
<div id="statusIndicator" data-bind=" css:{success:status==0, error:status=1 }">Status</div>
</div>

Is it possible to delete all scope variable of a controller? AngularJS

I am new to AngularJS and i dont know is it possible to delete all scope variables of a controller.I am using ng-controller with ng-repeat, like this.
<div ng-controller="main">
<div ng-repeat="x in list" ng-controller="test">
<input type="text" ng-model="text">
<span ng-click="remove($index)"> x </span>
<div>
</div>
JS
myapp.controller('main',function($scope){
$scope.list=[1,2,3,4]
})
myapp.controller('test',function($scope){
$scope.text="untitiled"
})
I want to remove the clicked scope.Can anyone help me or please suggest me a better way. Thanks
The question isn't very clear, but it looks like you may want to remove the item after clicking. Since you are passing into the remove function the index, you can splice it out. The DOM will autoupdate and remove that from the list:
$scope.remove = function(i) {
$scope.list.splice(i,1);
console.log($scope.list);
}
In the event you are doing something different in that you only want to hide it, you would push the index onto another array and then use something like ng-show or ng-hide.
$scope.remove2 = function(i) {
$scope.hideList.push(i);
}
$scope.shouldHide = function(i) {
return $scope.hideList.indexOf(i)!=-1;
}
<div ng-repeat="number in list2" >
{{number}}
<span ng-hide='shouldHide($index)' ng-click="remove2($index)"> x </span>
</div>
Here is a simple example of both scenarios. In real life, usually we are dealing with arrays of objects and what you might be doing is setting a property on one of the objects to hidden and controlling it that way.
Demo: http://plnkr.co/edit/G7UINKUCBJ4yZhQNtuJ2?p=info
If you actually want to remove all the keys from the scope:
function removeKeys() {
for(key in $scope) {
if (key.substr(0,1)!='$' && key!='this')
delete $scope[key];
}
}

AngularJS Function Trigger Reason

I am following the basic AngularJS tutorials at 'http://angularjs.org/' but I am slightly confused about the reason behind certain functions being triggered.
The their ToDo List app, they have the follows JS within the controller:
$scope.remaining = function() {
var count = 0;
angular.forEach($scope.todos, function(todo) {
count += todo.done ? 0 : 1;
});
return count;
};
Which is linked to the following HTML:
<div ng-controller="TodoCtrl">
<span>{{remaining()}} of {{todos.length}} remaining</span>
[ archive ]
<ul class="unstyled">
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.done">
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
</div>
However, when a checkbox is selected/deselected, I don't see how/where the $scope.remaining function is triggered to then update the values in the UI. There are other scope functions, but they don't seem to get called in this scenario, so what is special about this function?
The function remaining is used in an Expression (e.g. {{}}) angular creates watches for these expressions. So everytime a digest loop happens your function get called.

Resources