why the ng-class not changed? - angularjs

Examples of the problem:
http://jsfiddle.net/paloalto/DTXC2/
HTML:
<div ng-app="app">
<div id="wrapper" ng-controller="AppController" ng-class="showChatPanel">
<div id="tabBar" class="ui vertical icon menu inverted" ng-controller="TabBarController">
<a class="item switchChatBtn" data-tab="showChatWraper">Open Chat Panel</a>
</div>
<div id="chatWraper" class="ui segment">Chat Panel Opend!!</div>
</div>
</div>
Javascript:
angular.module('app', ['app.controllers']);
var controllers = angular.module('app.controllers', []);
controllers.controller('AppController', function AppController($scope, $log, $http) {
$scope.showChatPanel = '';
$scope.$on("switchChatPanel", function (event, msg) {
console.log(msg);
$scope.showChatPanel = msg;
console.log($scope.showChatPanel);
// $scope.$broadcast("switchChatPanel-done", msg);
});
$scope.$watch('showChatPanel', function(newVal, oldVal) {
if(newVal){
console.log('yeah! It is a newVal !!!');
} else {
console.log('still oldVal ');
}
});
});
controllers.controller('TabBarController', function TabBarController($scope, $log, $http) {
var tabBarItem =$('#tabBar > .item');
tabBarItem.click(function(){
var tabClass = $(this).data('tab');
console.log(tabClass);
$scope.$emit("switchChatPanel", tabClass);
});
});
CSS:
#chatWraper {
display:none;
}
.showChatWraper #chatWraper{
display:block;
}
=====
I finally solved it using jQuery, but I still wonder why angular not success.
controllers.controller('TabBarController',function TabBarController ($scope,$log,$http) {
var tabBarItem =$('#tabBar > .item');
var chatPanelOpen = false;
tabBarItem.click(function(){
var tabClass = $(this).data('tab');
if(!chatPanelOpen){
$('#wrapper').addClass(tabClass);
chatPanelOpen = true;
} else{
$('#wrapper').removeClass(tabClass);
chatPanelOpen = false;
}
})
})
https://gist.github.com/naoyeye/7695067
========
UPDATE
http://jsfiddle.net/paloalto/DTXC2/17/

You shouldn't be doing DOM manipulation like that in the controller. The correct way to do this is like this
<div ng-controller="TabBarController">
<div ng-click="toggleChatPanel()" ng-class="{tabClass: isChatPanelOpen}">
</div>
controllers.controller('TabBarController', function ($scope) {
$scope.isChatPanelOpen = false;
$scope.toggleChatPanel = function () {
$scope.isChatPanelOpen = !$scope.isChatPanelOpen;
};
});

Related

Scope from controller does not pass to directive

I have a html like this :
<div id="create-group" ng-controller="groupCreateController">
<div id="container">
<h1>Create group</h1>
<div class="row">
<div class="col-md-4"><input placeholder="Group Name.." ng-model="group.name"></div>
<div class="col-md-8">
<label>Group Description : </label>
<textarea ng-model="group.description"> </textarea>
</div>
</div>
<br/>
<div class="row">
<div class="col-sm-6">
<usermgr-permission-list group="group"></usermgr-permission-list>
<button type="button" class="btn btn-md btn-primary" ng-click="btnSave_click($event)">SAVE</button>
</div>
<div class="col-sm-6">
<usermgr-user-list group="group"></usermgr-user-list>
</div>
</div>
</div>
</div>
My controller is :
(function (module) {
'use strict';
module.controller('groupCreateController', function ($scope, $rootScope, $routeParams, $location, userGroupService, $mdDialog) {
$scope.group = [];
$scope.init = function () {
if ($routeParams.hasOwnProperty('id')) {
//edit mode
// $scope.trans.heading = 'Edit Release';
// $scope.trans.saveBtn = 'Save';
var id = parseInt($routeParams.id);
getUserGroup(id);
} else {
$scope.group[0].id = 0;
$scope.group[0].permissions = [];
$scope.assignedPermissions = [];
$scope.enrolledUsers = [];
$scope.group[0].users = [];
$scope.group[0].name = '';
$scope.group[0].description = '';
}
};
function getUserGroup(id) {
userGroupService.getbyid(id).then(function (info) {
if (info !== undefined && info.id === id) {
$scope.group[0].id = info.id;
$scope.group[0].name = info.name;
$scope.group[0].description = info.description;
console.log($scope.group);
// $rootScope.$broadcast('rCube-user-mgt-users-list', info.id);
// $rootScope.$broadcast('rCube-user-mgt-permissions-list', info.id);
}
else {
}
}).catch(function (exception) {
console.error(exception);
});
}
$scope.init();
});
})(angular.module('r-cube-user-mgt.user-group'));
I have two custom directives in the first block of code for user permissions and users. The group scope that i pass with the directive does not contain the values i put in the getUserGroup(id) function. The group name and group description shows up so the scope.group in the controller is filled, however thats not the case once i pass it to my directives. here is the directives code as well :
permissions list :
(function (module) {
'use strict';
module.directive('usermgrPermissionList', function () {
return {
restrict: 'E',
scope:{
group: '='
},
controller: function ($scope, permissionService) {
$scope.updatedPermissions=[];
console.log($scope.group); //it doesnt have the values from the controller ..
if (!$scope.group.hasOwnProperty('permissions')) {
$scope.group.permissions = [];
}
function getData() {
console.log("inside getDAta for permission list" + $scope.group.id;
permissionService.getPermissionsFiltered($scope.group.id).then(function (info) {
if (info && info.length > 0) {
console.log(info);
$scope.group.permissions = info.map(function (a, index, array) {
return {
id: a.id,
name: a.name,
description: a.description,
assigned: a.assigned
};
});
}
}).catch(function (exception) {
console.error(exception);
});
} //end of getData()
$scope.init = function () {
getData();
};
$scope.init();
},
templateUrl: 'r-cube-user-mgt/permission/list/list.tpl.html'
};
});
})(angular.module('r-cube-user-mgt.permission'));
can anyone help?
you cannot assign property to an array like this $scope.group.id = 0;
either make $scope.group object
$scope.group = {};
or add properties to an index
$scope.group = [];
$scope.init = function () {
if ($routeParams.hasOwnProperty('id')) {
//edit mode
// $scope.trans.heading = 'Edit Release';
// $scope.trans.saveBtn = 'Save';
var id = parseInt($routeParams.id);
getUserGroup(id);
} else {
$scope.group[0].id = 0;
$scope.group[0].permissions = [];
$scope.assignedPermissions = [];
$scope.enrolledUsers = [];
$scope.group[0].users = [];
$scope.group[0].name = '';
$scope.group[0].description = '';
}
};
So I solved the issue by adding broadcast to send the id when the directive loads. This worked!
in the Group controller i add broadcast and send the group.id
function getUserGroup(id) {
userGroupService.getbyid(id).then(function (info) {
if (info !== undefined && info.id === id) {
$scope.group.id = info.id;
$scope.group.name = info.name;
$scope.group.description = info.description;
console.log($scope.group);
$rootScope.$broadcast(rCubeTopics.userMgtPermissionLoadData, $scope.group.id);
}
}).catch(function (exception) {
console.error(exception);
});
}
and in the permission directive get that broadcast :
$scope.$on(rCubeTopics.userMgtPermissionLoadData, function (event, id) {
console.log($scope.group.id);
getData();
});

md-checkbox does not work with ng-click

I want to save position each time when I change checkbox:
<h1 class="md-display-2">Simple TODO ng app</h1>
<h2 class="md-display-3"></h2>
<div ng-include src="'todo/add.html'"></div>
<div>
<div layout="row">
<div flex class="md-title">Scope</div>
<div flex="10" class="md-title">Till date</div>
<div flex="10" class="md-title">Is reached?</div>
<div flex="10" class="md-title">
<span ng-click="todoctrl.show_add()" class="material-icons controls">add</span>
</div>
</div>
<div layout="row" ng-repeat="todo in todoctrl.todos track by $index">
<div flex ng-class="{true:'striked', false:'simple'}[todo.reached]">{{todo.name}}</div>
<div flex="10">
{{todo.tillDate | date:'dd/MM/yyyy'}}
</div>
<div flex="10">
<md-checkbox ng-model="todo.reached" aria-label="Is reached" ng-click="todoctrl.changeState(todo.name)"></md-checkbox>
</div>
<div flex="10">
<span ng-click="todoctrl.deleteScope(todo.name)"
class="material-icons controls">clear</span>
</div>
</div>
</div>
In this case controller is touched (I tried with to debug with console log), but the checkbox value is not changed before page reload. After reload the value is checkbox is presented as expected.
If I remove ng-click="todoctrl.changeState(todo.name)" then checkbox is working good, but no info is sent to controller.
This is my service:
(function() {
'use strict';
angular.module('app').service('ToDoService', ToDoService);
ToDoService.$inject = ['JsonService'];
function ToDoService(JsonService) {
return {
deleteScope : deleteScope,
submitScope : submitScope,
changeState : changeState,
getData : getData
}
function getData() {
var todos = JsonService.getData();
return todos;
}
function deleteScope(arr, scope) {
arr.splice(findElementByScope(arr, scope), 1);
JsonService.setData(arr);
}
function submitScope(arr, scope, tillDate) {
var newTodo = {};
newTodo.name = scope;
newTodo.reached = false;
newTodo.tillDate = tillDate;
arr.push(newTodo);
JsonService.setData(arr);
}
function changeState(arr, scope) {
console.log("Service change state for scope: " + scope);
var todo = {};
var index = findElementByScope(arr, scope);
todo = arr[index];
todo.reached = !todo.reached;
JsonService.setData(arr);
}
function findElementByScope(arr, scope) {
for (var i = arr.length; i--;) {
if (arr[i].name == scope) {
return i;
}
}
return -1;
}
}
})();
And this is the Controller:
(function() {
'use strict';
angular.module('app').controller('ToDoController', ToDoController);
function ToDoController(ToDoService) {
var vm = this;
vm.show_form = false;
vm.todos = ToDoService.getData();
vm.scope = '';
vm.show_add = show_add;
vm.submitScope = submitScope;
vm.deleteScope = deleteScope;
vm.changeState = changeState;
function show_add() {
console.log("Controller show add");
vm.show_form = true;
}
function submitScope() {
ToDoService.submitScope(vm.todos, vm.scope, vm.tillDate);
vm.show_form = false;
vm.scope = '';
}
function deleteScope(scope) {
ToDoService.deleteScope(vm.todos, scope);
}
function changeState(scope) {
ToDoService.changeState(vm.todos, scope);
}
}
})();
Use ng-change instead of ng-click
<md-checkbox ng-model="todo.reached" aria-label="Is reached" ng-change="todoctrl.changeState(todo.name, todo.reached)"></md-checkbox>
ng-change trigger after value change in model

Angular Modal triggering an ng-hide/ng-show

I'm building out a modal that takes 10 lines of input and when clicked to close randomizes them and "should" display out side the modal. Through other research I have found that I must use a service to make everything work right. However this service is not properly changing over my var for changing over true/false for my ng-hide.
Some code below
Main HTML
<body ng-controller="ModalDemoCtrl">
<my-modal-content></my-modal-content>
<button class="btn btn-small"
ng click="open(lg,'ModalInstanceCtrl')">Add</button>
<ul ng-controller="MainCtrl" >
<button class="btn" ng-click="test()">Test</button>
<li ng-hide="toggle" ng-repeat="random in randomTeams">{{random.team}}</li>
</ul>
<script src="js/vendor/angular.js"></script>
<script src="js/vendor/angular-animate.js"></script>
<script src="js/vendor/angular-ui.js"></script>
<script src="app.js"></script>
<script src="js/Modal.js"></script>
<script src="js/setTeams.js"></script>
<script src="js/randomizeTeamservice.js"></script>
</body>
My-modal-content
<div class="modal-header">
<h3 class="modal-title">Set Team Names</h3>
</div>
<div class="modal-body" ng-controller="MainCtrl">
<div class="input-append" ng-repeat="team in teams | limitTo: 10">
<input class="form-control" type="text" ng-model="team.team"
placeholder="Team {{$index + 1}}" value="{{$index}}">
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="ok();
add(this)">OK</button>
<button class="btn btn-warning" type="button" ng-
click="cancel()">Cancel</button>
</div>
</div>
Modal Controller
app.controller('ModalDemoCtrl', function ($scope, $uibModal) {
$scope.animationsEnabled = true;
$scope.open = function (size,controller) {
$uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: controller ,
size: size,
});
};
});
// Please note that $uibModalInstance represents a modal window (instance)
dependency.
// It is not the same as the $uibModal service used above.
app.controller('ModalInstanceCtrl', function ($scope, $uibModalInstance, randomService) {
$scope.toggle = randomService.showTeams();
$scope.ok = function () {
$uibModalInstance.close({
}
);
$scope.toggle = false;
console.log($scope.toggle);
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
});
Finally the Service
app.factory("randomService", function(){
var teams = [{},{},{},{},{},{},{},{},{},{}];
var randomTeams = teams.slice(0);
var showTeams = true;
return{
randomTeams: function(){
return randomTeams;
},
teams: function(){
return teams;
},
showTeams: function(){
return showTeams;
}
}
});
So why won't the ng-hide work?
Problem solved. Moved some things around but here it is.
Moved the randomize function to the controller and added a getter so a function will retrieve the toggle (true/false) value.
app.controller('MainCtrl', function($scope, randomService) {
$scope.teams = randomService.teams();
$scope.randomTeams = randomService.randomTeams();
$scope.toggle = function(){
return randomService.getTeams();
}
$scope.add = function(team, show) {
for( var i = 0; i < 10; i++){
$scope.teams.splice(i, 1, team.teams[i]);
}
randomService.shuffle($scope.randomTeams);
$scope.toggle();
};
});
In the service factory in addition to adding the shuffle function and a getter function. I added a line of code that will change the showTeams from true to false.
app.factory("randomService", function(){
var teams = [{},{},{},{},{},{},{},{},{},{}];
var randomTeams = teams.slice(0);
var showTeams = true;
return{
randomTeams: function(){
return randomTeams;
},
teams: function(){
return teams;
},
shuffle: function shuffle(array) {
showTeams = false;
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
},
getTeams: function(){
return showTeams;
},
}
});
lastly ng-hide="toggle: changed to ng-hide="toggle()"

Unable to get the scope data to the html page using factory in angularjs

I'm able to send the same json data from home.js to content.js.But I'm unable to populate the content.js scope data into the html page
Can anyone please help me out regarding this issue ...
My home.js:
angular.module('myApp')
.controller('firstCtrl', ['$scope', 'myService',
function ($scope,myService) {
$scope.list1= [];
$scope.list2= [];
var sampleItem = this.item;
myService.setJson(sampleItem);
$.each($scope.samples, function (i, x) {
if (x.name === sampleItem .secName && x.id === sampleItem .id) {
if (sampleItem .secName === $scope.secsList[0]) {
$scope.list1.push(x);
}
else {
$scope.list2.push(x);
}
$scope.myData = x.dataList;
}
});
});
My content.js :
angular.module('myApp')
.controller('secondCtrl', function ($scope,myService) {
$scope.myreturnedData = myService.getJson();
console.log($scope.myreturnedData);
})
.factory('myService', function(){
var sampleItem = null;
return {
getJson:function(){
return sampleItem;
},
setJson:function(value){
sampleItem = value;
}
}
});
My content.html :
<div ng-controller="secondCtrl" > {{myreturnedData.sampleName}}</div>
My home.html:
<div ng-controller="firstCtrl" ng-repeat="item in list1" >
<div > {{item.sampleName}} </div>
</div>
This is work solution jsfiddle
angular.module('ExampleApp',[])
.controller('firstCtrl', function($scope, myService) {
$scope.sampleItem = {
sampleName: "sampleName"
};
myService.setJson($scope.sampleItem);
}
)
.controller('secondCtrl', function($scope, myService) {
$scope.myreturnedData = myService.getJson();
console.log($scope.myreturnedData);
})
.factory('myService', function() {
var sampleItem = null;
return {
getJson: function() {
return sampleItem;
},
setJson: function(value) {
sampleItem = value;
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="firstCtrl">
<h2>
firstCtrl
</h2>
<input ng-model="sampleItem.sampleName">
</div>
<div ng-controller="secondCtrl"> <h2>
secondCtrl
</h2>{{myreturnedData.sampleName}}</div>
</div>

How can I use the exact same array from one service in two controllers?

I have this code:
controller:
function deleteRootCategory(){
$scope.rootCategories[0] = '';
}
function getCategories(){
categoryService.getCategories().then(function(data){
$scope.rootCategories = data[0];
$scope.subCategories = data[1];
$scope.titles = data[2];
});
}
getCategories();
service:
var getCategories = function(){
var deferred = $q.defer();
$http({
method:"GET",
url:"wikiArticles/categories"
}).then(function(result){
deferred.resolve(result);
});
}
return deferred.promise;
}
html:
<div ng-controller="controller">
<div ng-repeat="root in rootCategories"> {{root}} </div>
<div ng-repeat="sub in subCategories"> {{sub}} </div>
<div ng-repeat="title in titles">{{title}}</div>
</div>
html2:
<div ng-controller="controller">
<div ng-include src="html"></div>
<button ng-click="deleteRootCategory()">Del</button>
</div>
When I click the deleteRootCategory-button the array $scope.rootCategories is updated, but the view won't ever change.
What am I missing?
Thanks
You will probably want to have a broadcast event set up when the value is changed in the service. Something like this.
.service("Data", function($http, $rootScope) {
var this_ = this,
data;
$http.get('wikiArticles/categories', function(response) {
this_.set(response.data);
}
this.get = function() {
return data;
}
this.set = function(data_) {
data = data_;
$rootScope.$broadcast('event:data-change');
}
});
Have both controllers waiting for the event, and using the set to make any changes to the array.
$rootScope.$on('event:data-change', function() {
$scope.data = Data.get();
}
$scope.update = function(d) {
Data.set(d);
}

Resources