Angular.js how to apply cursor: no-drop in a css class - angularjs

what I am trying to do is: make the cursor:no-drop; using css for this, fine works, but the problem is I am still getting the click when I click in the Icon.
If you see my Icon turn to red and I inserted cursor:no-drop; by css. for the user not be able to click, but the click still on how can I solve this? and block the click when the Icon turns to red?
thank you.
html + angular
<div ng-app>
<div ng-class="{'selected-gamepad':tog==1}">
<br>
<i class="fa fa-lg fa-gamepad" ng-class="{'gamepad-blue': iTog1}"
ng-click="iTog1 = !iTog1"></i>
<span id='1' ng-click='tog=1; iTog1 = false;'>span 1</span>
</div>
<div ng-class="{'selected-gamepad':tog==2}">
<br>
<i class="fa fa-lg fa-gamepad" ng-class="{'gamepad-blue': iTog2}" ng-click="iTog2 = !iTog2"></i>
<span id='2' ng-click='tog=2; iTog2 = false;'>span 2</span>
</div>
</div>
css:
.selected-gamepad > span {
border: dotted pink 3px;
}
.selected-gamepad > i {
color: red;
cursor:no-drop;
}
.gamepad-blue,
.selected-gamepad .gamepad-blue{
color: blue;
}
jsfiddle: http://jsfiddle.net/zvLvg/290/

Changing the cursor property in CSS doesn't magically disable clicking - it just changes the cursor so it looks like you can't click. If you want to disable clicking, you need some additional logic in your code.
I've edited the code a bit to clean it up and moved some logic to controller. The code of course could be much better, but I leave it up to you - try to read some tutorials about it and get familiar with cleaner Angular syntax to write better code :-).
Coming back to the problem - what you really needed to do was to block player from clicking, when the pad is selected. I did it by adding a simple checking with if statement inside toggle function:
View:
<div ng-app="app">
<div ng-controller="GameController as vm">
<div ng-class="{'selected-gamepad':vm.tog==1}">
<br>
<i class="fa fa-lg fa-gamepad" ng-class="{'gamepad-blue': vm.iTogs[1]}" ng-click="vm.toggle(1)"></i>
<span id='1' ng-click='vm.selectPad(1)'>span 1</span>
</div>
<div ng-class="{'selected-gamepad':vm.tog==2}">
<br>
<i class="fa fa-lg fa-gamepad" ng-class="{'gamepad-blue': vm.iTogs[2]}" ng-click="vm.toggle(2)"></i>
<span id='2' ng-click='vm.selectPad(2)'>span 2</span>
</div>
</div>
</div>
Logic:
<script>
// Register module
angular.module('app', []);
// Create controller
angular.module('app')
.controller('GameController', function() {
var self = this;
self.tog = null;
self.iTogs = [false, false];
self.toggle = function(index) {
if (self.tog != index) {
self.iTogs[index] = !self.iTogs[index];
}
}
self.selectPad = function(index) {
self.tog = index;
self.iTogs[index] = false;
}
});
</script>
Here's working plunker:
http://jsfiddle.net/zvLvg/291/
A little explanation
What I did was move some of the logic to controller. Controllers let you separate different parts in the application and have more control over them. Also, the code is much cleaner when you use functions instead of direct expressions inside directives (like you did with ng-click earlier).
I've also created an array instead of naming variables with numbers. Further improvements would be to use ng-repeat to avoid code repetition - divs inside your pads list are pretty much the same and could be substituted with one div and ng-repeat. Also, names of the properties could be better - now they don't really say what they mean if you look at them.
I hope these small tips will help you to get better with Angular and with programming at all. :-)

Related

Angularjs toggle panel & sub-panel controls

there are multiple panels and sub-panels (DIVs), that i need to show its (panel) controls on click to do specific tasks. The project is cv builder with front-end editing capabilities. So in regard to show/hide panels, my approach is very basic so hoping there would be much better way to getting this done.
Here is HTML Markup
<div class="panel component-about" ng-class="{'active': aboutPanel}" ng-click="activePanelAbout()">
<h2 class="title">Some Title (input)</h2>
<div class="panel-body">
Some text (textarea)
</div>
<div class="panel-hover-controls">
<span class="fa fa-pencil"></span>
<span class="fa fa-cog"></span>
<ul class="panel-dropdown" ng-class="{'active': aboutToggle}">
<li><label class="input-switch"><input type="checkbox" ng-model="aboutTitleShow" ><span class="slider round"></span></label> Show Title</li>
</ul>
</div>
</div>
<div class="panel component-experience" ng-class="{'active': expPanel}" ng-click="activePanelExp()">
<h2 class="title">Some Title (input)</h2>
<div class="panel-body">
<ul class="panel-componenets">
<li ng-repeat>
Title
Content
</li>
</ul>
</div>
<div class="panel-hover-controls">
<span class="fa fa-pencil"></span>
<span class="fa fa-cog"></span>
<ul class="panel-dropdown" ng-class="{'active': aboutToggle}">
<li><label class="input-switch"><input type="checkbox" ng-model="aboutTitleShow" ><span class="slider round"></span></label> Show Title</li>
</ul>
</div>
</div>
<div class="panel component-skills" ng-class="{'active': skillsPanel}" ng-click="activePanelSkills()">
<h2 class="title">Some Title (input)</h2>
<div class="panel-body">
<ul class="panel-dropdown" ng-class="{'active': aboutToggle}">
<li><label class="input-switch"><input type="checkbox" ng-model="aboutTitleShow" ><span class="slider round"></span></label> Show Title</li>
</ul>
</div>
<div class="panel-hover-controls">
<span class="fa fa-pencil"></span>
<span class="fa fa-cog"></span>
<ul class="panel-dropdown" ng-class="{'active': aboutToggle}">
<li><label class="input-switch"><input type="checkbox" ng-model="aboutTitleShow" ><span class="slider round"></span></label> Show Title</li>
</ul>
</div>
</div>
Further please check markup figure in (below) screenshot.
In reference to attached screenshot, there are multiple panel sections and most of panels also have sub-panels and each panel has its own control type which need to be show on click.
Here is JS (Controller)
// for setting popups
$scope.aboutToggle = false;
$scope.expToggle = false;
$scope.skillToggle = false;
// about panel
$scope.activePanelAbout = function() {
$scope.aboutPanel = true;
$scope.expPanel = false;
$scope.skillPanel = false;
}
// experience panel
$scope.activePanelExp = function() {
$scope.aboutPanel = false;
$scope.expPanel = true;
$scope.skillPanel = false;
}
// skill panel
$scope.activePanelSkill = function() {
$scope.aboutPanel = false;
$scope.expPanel = false;
$scope.skillPanel = true;
}
Now i think the picture should be clear. The panels are toggling actually, but i require more better approach something like this that we use to do in javascript/jquery.
I hope i have covered all aspects of my question, if not please do guide me so i can clarify myself. I'm looking forward for your guidance.
Thanks in advance.
this in AngularJS ends up a bit different than plain old JS. Since a controller contains its own $scope in relation to the DOM of which the controller is instantiated, this doesn't always refer to the object that calls a function, etc. So I can think of two options:
First maybe simplify how you're changing the active class for each panel and it's children. So maybe just:
$scope.activePanel = "";
$scope.ChangeActivePanel = function(newPanel) {
$scope.activePanel = newPanel;
}
And then change the ng-class for each panel to ng-class="{'active': activePanel == 'about'}" or ng-class="{'active': activePanel == 'skills'}", etc. Then change ng-click on the panels to ng-click="ChangeActivePanel('about')" or whatever to update the variable. In all honesty, just ng-click="activePanel = 'about'" would work but the ChangeActivePanel function could be expanded to handle behavior of the children panel elements as well. Just a thought rather than having three different functions and toggling all of these variables.
Second option is to create controllers for each panel by declaring ng-controller="aboutController" or ng-controller="skillsController" to each panel and then each panel would have it's own $scope but you'll have to declare and attach each controller to the app module and you'll run into headaches if you need to share data across controllers and will have to use factories/services, etc. I think that's overkill for something like this. Plus, it's difficult to manage which $scope is which across multiple controllers within the same view.
Hopefully this gives you something to work with.

AngularJS- How to handle each button created by ng-repeat

I am new to AngularJS.
I have created <li> to which I used ng-repeat.
<li> contains images and buttons like like, comment and share which is inside <li> and created by ng-repeat.
I have made function which will replace empty like button to filled like button (By changing background image of button).
But problem is this trigger applies to only first like button and other buttons does not change.
How can I fix this?
Code:
HTML:
<html>
<body>
<ul>
<li ng-repeat="media in images"><div class="imgsub">
<label class="usrlabel">Username</label>
<div class="imagedb">
<input type="hidden" value="{{media.id}}">
<img ng-src="{{ media.imgurl }}" alt="Your photos"/>
</div>
<!-- <br><hr width="50%"> -->
<div class="desc">
<p>{{media.alt}}</p>
<input type="button" class="likebutton" id="likeb" ng-click="like(media.id)" ng-dblclick="dislike(media .id)"/>
<input type="button" class="commentbutton"/>
<input type="button" class="sharebutton"/>
</div>
</div> <br>
</li><br><br><br>
</ul>
</body>
</html>
JS:
$scope.like = function(imgid)
{
document.
getElementById("likeb").
style.backgroundImage = "url(src/assets/like-filled.png)";
alert(imgid);
}
$scope.dislike = function(imgid)
{
document.
getElementById("likeb").
style.backgroundImage = "url(src/assets/like-empty.png)";
}
Thanks for help & suggestions :)
The id for each button should be unique but in your case, it's the same for all buttons ('likeb').
You can set the value of the attribute 'id' for each button dynamically by using '$index' and passing '$index' to the functions as follows:
<input type="button" class="likebutton" id="{{$index}}" ng-click="like($index)" ng-dblclick="dislike($index)"/>
Then in your controller, you can use the functions with the passed value.
For example,
$scope.like = function(index)
{
document.
getElementById(index).
style.backgroundImage = "url(src/assets/like-filled.png)";
}
Another good alternative in your case would be to use the directive ngClass.
use 2 css class for styling liked and disliked state, and then put the class conditionally with ng-class instead of DOM handling. and if you really want to perform a DOM operation (I will not recommend) then you can pass $event and style $event.currentTarget in order to perform some operation on that DOM object.

How to bind a part of a variable already binded

I have a loop ng-repeat that displays sevral icons.
<div class="box">
<div class="box-body">
<div class="row" >
<div class="col-sm-6" style="margin-bottom: 5px;" ng-repeat="record in newlayout.display" align="center">
<a class="btn btn-app" ng-href="#newlayout/{{newlayout.url}}{{newlayout.itemValue}}" >
<span class="badge bg-yellow" style="font-size:22px;">{{record.numberOfSamples}}</span>
<i class="fa fa-{{newlayout.labStyle}}"></i> {{record.lab}}
</a>
</div>
</div>
</div>
</div>
My issue is that the second part of the binded variable itemValue should be dynamic
In my Js, I have this
newLayout.url = 'sublabs/?labName=';
newLayout.itemValue = 'record.lab';
The URL is dynamic.
When I click on the first displayed Icon, the url should look like this :
But it didn't work as I had a compilation error..
Does someone have an idea how to fix this:
http://localhost:8181/#/newlayout/sublabs?labName=PIA/C1 - Shiftlabo
Where the record value "PIA/C1 - Shiftlabo" change.
So basically here if I change
<a class="btn btn-app" ng-href="#newlayout/{{newlayout.url}}{{newlayout.itemValue}}" >
{{newlayout.itemValue}} by {{record.lab}} it would work..but the {{record.**lab**}} should be dynamic as it will have another value when I click on the icon. It will change to {{record.subLab}}
Thanks
Use property acccessor bracket notation inside the binding:
<div>{{record[labOrSublab]}}</div>
JS
var isSublab = false;
$scope.labOrSublab = "lab";
$scope.clickHandler = function() {
isSublab = !isSublab;
$scope.labOrSublab = isSublab ? 'subLab' : 'lab';
};

Angularjs: how change icon when item is clicked

I know that this question has already some answers/solutions but none of them works for me most probably because this is the first time when I'm trying to implement something using Angularjs.
I have a div (title) that expands some info when it's clicked and I want to change the icon inside of it when that info is visible...
This is my code:
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon glyphicon-chevron-right"></i>
</div>
And this is what I tried to do, but not working because the div will not show the expanded info anymore:
<div class="title" ng-click="view_variables(request) = !view_variables(request)">
<i ng-class="{'glyphicon glyphicon-chevron-right':!view_variables(request), 'glyphicon glyphicon-chevron-left': view_variables(request)}"></i>
</div>
Controller code:
$scope.view_variables = function(req){
if (!req.enabled_variables && !req.disabled_variables) {
$http.get('/api/files/' + $scope.file_id + '/requests/' + req.id + '/variables')
.success(function(data){
variables = data.data;
req.enabled_variables = [];
req.disabled_variables = [];
for (i=0; i<variables.length; i++) {
if (variables[i].disabled == true) {
req.disabled_variables.push(variables[i]);
} else {
req.enabled_variables.push(variables[i])
}
}
});
}
req.show_variables = !req.show_variables;
}
The view_variables function doesn't return anything, so it will always be treated as false.
You want something like this:
<div class="title" ng-click="view_variables(request)">
<i ng-class="{'glyphicon glyphicon-chevron-right':!request.show_variables, 'glyphicon glyphicon-chevron-left': request.show_variables}"></i>
</div>
I think the problem is what you have going on in the ng-click attribute. By using "view_variables(request) = !view_variables(request)" are you not calling the view_variables function twice? Also, it seems strange to be assigning a value to a function call.
I would just keep ng-click="view_variables(request)" as you had in the first line of code, then have the view_variables function set a boolean somewhere in scope ($scope.data.view_vars) and have that determine ng-class for your i element.
Good luck!
--EDIT: Now that you've put up your controller, req.show_variables looks like a useful candidate
Calling a function inside ng-class is a bad idea. Why don't you use a flag for it.
eg.
inside controller-
$scope.view_variables = function(request){
//your code
$scope.isExpanded = !$scope.isExpanded;
};
and in html
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon" ng-class="{'glyphicon-chevron-right':!isExpanded, 'glyphicon-chevron-left':isExpanded}"></i>
</div>
May be Better this way using ng-show directive:
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon glyphicon-chevron-right" ng-show="!view_variables(request)"></i>
<i class="glyphicon glyphicon-chevron-left" ng-show="view_variables(request)"></i>
</div>
You could use ng-if directive like so:
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon glyphicon-chevron-right" ng-if="!view_variables(request)"></i>
<i class="glyphicon glyphicon-chevron-left" ng-if="view_variables(request)"></i>
</div>
assuming view_variables(request) returns true or false... maybe could replace it for req.show_variables.

Animate rows through a directive inside a ng-repeat

I'm building this application in Angular where a div table is formed by using ng-repeat through the following html:
HTML
<div ng-repeat="(key, value) in data.data.ipv4">
<div class="cellbody">{{value.descr}}</div>
<div class="cellbody">{{value.protocol}}</div>
<div class="cellbody">{{value.internip}}</div>
<div class="cellbody">{{value.internrange}}</div>
<div class="cellbody">{{value.externrange}}</div>
<div class="deletecell">
<span class="toggledelete" ng-click="deleteport($event, key, 4)">
<i class="icon-minus negativehover"></i>
</span>
<span class="toggledelete" style="display:none">
<span>PORT DELETED</span>
<span class="deletedportundo" ng-click="restoreport($event, $index, 4)">
UNDO
</span>
</span>
</div>
</div>
The last div of each row, has a visible clickable button which sends a delete order to the server via the deleteport() function, and then, if everything goes all right, starts an animation where the whole cell is hidden and the previously hidden span with class 'deletedportundo' shows up.
Anyway the thing is my controller looks like this:
Angular Javascript Controller
$scope.deleteport = function(e,f) {
postData.index = f;
$http.post('serverside/router.php', postData)
.success(function(data, status, headers, config){
if (data.status == 'ok') {
var elem = angular.element(e.target);
$(elem).parent().parent().parent().children('.cellbody').hide('fast');
$(elem).parent().parent().children('.toggledelete').toggle();
$(elem).parent().parent().parent().children('.deletecell').animate({
width: "100%"
}, 300 );
$(elem).parent().parent().parent().children('.deletecell').addClass('macdeleted');
}
});
}
Which visually works as expected, except that I am aware that I should not be manipulating the DOM in the controller; I have been unsuccessfully trying to integrate this into a directive, but because every row is independent of the others I have not been able to achieve the desired effect.
Daniel,
There is nothing wrong with manipulating DOM in the controller. However, I can suggest an easier way to do it than to navigate with those nasty parent().parent().parent().parent().parent() ... calls :) .
Just add an ng-show to the toggledelete div, than just do $scope.portDeleted = false in your controller. This also works for the .cellbody tags.
As for the .deletecell class you can use ng-class, and just do $scope.deletecell = some_value.
<div ng-class="{deletecell:deletecell}">
<span class="toggledelete" ng-click="deleteport($event, key, 4)">
<i class="icon-minus negativehover"></i>
</span>
<span class="toggledelete" style="display:none">
<span>PORT DELETED</span>
<span class="deletedportundo" ng-click="restoreport($event, $index, 4)">
UNDO
</span>
</span>
</div>
For animate, you can use ngAnimate (http://www.nganimate.org/)

Resources