How to mark multiple elements without clicking in angular? - javascript

I have the following code:
<table>
<tr ng-repeat="minute in hour.minutes track by $index">
<td class="{{minute.class}}" ng-mousedown="setTdCol(hour, minute)" > </td>
</tr>
</table>
setTdCol just changes minute.class causing the cell to change its background color.
My goal is to allow the user to mark multiple cells by pushing the mouse button once and then moving above the cells.
That is why I used ng-mousedown instead of ng-click, but still I have to release the mouse and click each column. What has to be changed?

Try to build your logic together with ng-mouseover and ng-mouseup.
For example you can set a boolean variable mouseDown to true with ng-mousedown and set it to false with ng-mouseup. That way in your ng-mouseover function you can check if the mouse is down or up and mark the elements you go over. You can for example store them in an array and if the element exists in that array on hover - remove it. Or set them to active / inactive with boolean ... etc.
Hope that helps you :)

You want to know when the mouse is down on the table and when it is, which minutes its hovering above. You can set a flag to indicate if the mouse is down on the table that will vary when the table's ng-mouseup and ng-mousedown are invoked, and give an ng-mouseover function to each cell that will check if this flag is true.
<table ng-mousedown="isDown = true" ng-mouseup="isDown = false">
<tr ng-repeat="minute in hour.minutes track by $index">
<td ng-style="minute.class" ng-mouseover='setTdCol(hour, minute)'>aaa</td>
</tr>
</table>
In the example above, isDown is the flag. Now you just need to wrap setTdCol function in an if that checks if is down is true. just don't forget to initialize $scope.isDown in the controller
...
$scope.isDown = false;
$scope.setTdCol = function(hour, minute) {
if($scope.isDown) {
...
}
};
...

Related

Angular / HTML clear input events

I am working on an Angular app and I seem to have stumbled upon a small bug/problem. I have 4 clickable areas in my html and each click calls a function of the component's .ts script. So far, so good. I want to make each area only be clickable once, however this doesn't seem to work the way I am doing it (and I do not quite understand why).
clicked(event: Event): void {
// Get coordinates of clicked cell
var elementId: string = (event.target as Element).id;
if(this.answersGiven.includes(elementId)) {
console.log("included");
return;
}
this.answersGiven.push(elementId);
And the html
<table>
<tr>
<td id="A1" (click)="clicked($event);">
</tr>
So after the first click, the answer should be pushed into the array which is working just fine. However after the second click on the same cell it is not jumping into the if condition. When clicking a third time on the same cell, it works however. When i log the events, the second time I only get "" instead of the element id. My guess is that this could have something to do with some sort of buffer or that the button is pushed down and stays down but I couldn't find anything realted to that.
Glad for any help, thank you :)
You should try this:
HTML:
<table>
<tr>
<td (click)="clicked($event, 'A1');">
</tr>
TS:
clicked(event: Event, cod: string): void {
// Get coordinates of clicked cell
var elementId: string = (event.target as Element).id;
if(this.answersGiven.includes(cod)) {
console.log("included");
return;
}
this.answersGiven.push(cod);
the Angular way of build your HTML have probably changed your <td id="A1", check into your browser developer tool if the ID keeps the same.

Add clickable element within a clickable table row

Let's say I have a table row with a clickable element in it:
<tr ng-repeat="product in products" onclick="showProductDetail()">
<td>{{product.id}}</td>
<td>{{product.title}}</td>
<td>{{product.price}}</td>
<td>
<switch id="enabled" name="enabled" ng-model="product.enabled" ng-change="enableProduct()"></switch>
</td>
</tr>
I'm using Angular UI Switch but the issue would be the same for any clickable element.
How do I make the row clickable but isolate the behavior of the switch? Currently it tries to do both, resulting in wonky behavior. I know I could just make each cell except that last one clickable, but is there a cleaner way?
If Dmitry's answer does not work.
Try calling the ng-change with enableProduct($event)
And within that function, call
function enableProduct($event) {
$event.stopPropagation();
...
}
I believe the <switch> handler should stop the event propagation. Try to return false from you ng-change handler. E.g.
ng-change="enableProduct(); return false"

alternating class in ng-repeat using scope var without binding

I have a nested ng-repeat on a table. It is an accordion table with child rows for each parent row. In order to accomplish this I created a <tbody> for each parent item, placing the parent row in a <tr> and then using ng-repeat to add all the child rows. Due to the multiple <tbody> elements the zebra striping on the table gets thrown off. Another wrinkle is that the table has the ability to collapse/expand child rows and I need the striping to be correct for whichever rows are visible. So I am trying to manually add striping classes. I'm using Angular's ng-init to toggle a scope variable, and then using ng-class to apply it. The problem is that it appears to be bound to the final state of the variable rather than what it was as the iterator was rendering the row.
HTML:
<tbody ng-repeat="parentRow in myData" ng-init="changeRowClass($even)">
<tr ng-class="{'industry-payments-even-row':industryRowEven,'industry-payments-odd-row':!industryRowEven}">
<td>{{parentRow.industryCode}} - {{parentRow.industryCodeDescription}}</td>
<td class="numeric">{{parentRow.ValueOneSum}}</td>
<td class="numeric">{{parentRow.ValueTwoSum}}</td>
</tr>
<tr ng-repeat="childRow in parentRow.childIndustries" ng-init="changeRowClass($even)" ng-class="{'industry-payments-even-row':industryRowEven,'industry-payments-odd-row':!industryRowEven}">
<td>{{childRow.industryCode}} - {{childRow.industryCodeDescription}}</td>
<td class="numeric">{{childRow.ValueOne}}</td>
<td class="numeric">{{childRow.ValueTwo}}</td>
</tr>
</tbody>
Controller code:
$scope.industryRowEven = false;
$scope.changeRowClass = function(isEven) {
$scope.industryRowEven = isEven;
};
I need each iteration (of parent OR child) to reverse the class for the next one (I'm leaving out the issue of if the child is visible or not for now to keep this more simple). I can see in the debugger that the variable is getting toggled properly on each iteration. The problem is that the ng-class seems to be bound to the current state in scope so when it is true it would apply one class, but then next time it is false and switches the class for all of them.
I need it to just print the class according to the variable state at the time it renders that row, and then ignore the variable unless the ng-repeat is started over (like for sorting or toggling visibility, etc.)
Is there a way to stop the binding?
AngularJS has this build in with directives called ngClassOdd and ngClassEven.
They work just like ngClass, but only on odd/even items inside an ngRepeat.

Toggle with ! operator not working on page load JavaScript

I have an onClick (using angular.js ng-click) where i have to toggle color of a table row with on click.
This is the initial implementation.
<tr>
<td ng-class="{'setType': types.isTypeSet('TYPE') == true}" ng-click="types.setType('TYPE')">
<img class="typebox-img" src="">
<div class="typebox">TYPE</div>
</td>
</tr>
where 'type' is the type of table row and 'types' is the angular controller.
types.setType(type):
...
this.types[type] = ! this.types[type];
...
while this toggles values from the second click on, it doesnt change the value on the first click.
I implemented the functionality using the if-else statement, but cant figure out why this wont work as it is a pretty basic thing to do.
this.types[type] is set to false as default.
Could someone explain why is this happening..
It doesn't surprise me that this doesn't work:
ng-click='types.setType('type')
Use " for the inner quotes to make the parser understand what you're trying to do (or the other way around):
ng-click='types.setType("type")'
Incidentally, you don't need a function to do this. Just initialize in your controller a bool:
$scope.toggle = true
And use in your view like this:
ng-click='toggle = !toggle'

use JQuery to find the collective radio button group name

I've asked a lot of jQuery questions recently as I'm trying to use it rather good old Javascript, as I mentioned in previous questions, "I'm currently having to extend an very old ASP.NET site which has a database generated front end and is a behemoth of an application, it needs completely rewriting - however I've been told to add to it than redevelop it "
Now what I'm doing is once the backend is rendering a table to the interface I wish to loop through the tr elements of the table, within one of the td elements of the tr there are two radio buttons. I need to determine the name of the radio button group as I don't define them, the systems does using a GUID or something?
This is the table for example...
<table id="tableID">
<tr>
<td class="qCol">
<!-- Label here -->
</td>
<td class="qCo2">
<!-- img here -->
<!-- and a text box -->
</td>
<td class="qCo3">
<!-- select menu here -->
</td>
<td class="qCo4">
<!-- radio buttons here -->
</td>
<td class="qCo5">
<!-- select menu here -->
</td>
<td class="qCo6">
<!-- hidden validation image here -->
</td>
<tr>
</table>
Okay, I'm looping through the table and at the same time switching the innerHTML of one cell to another and hiding some of the rows, I'll be adding functionality to show these later, here's the jQuery:
$('#tableID tr').each(function (i) {
/*switch select and validation and clear */
$(this).children('td.qCol').html($(this).children('td.aCol5').html());
$(this).children('td.aCol5').html($(this).children('td.vCol'.html(""));
/* hide all but the first row*/
if (i >= 1) {
$(this).hide();
}
now I'm trying to determine the name attribute of the radio buttons that will be in the cell with class .qCo4, however I'm having no luck as the following returns an error and is "undefined"...
/* get the radio button name and check if either are selected*/
// check something exists...
if ($('input:radio', this).attr('name')) {
var thisRadioName = $(this).closest("input:radio").attr('name').val();
alert(thisRadioName);
}
$this is the tr element, so should I be using child rather than closest? If this makes no sense I can expand and explain better.
you should use find() or children(). closest() goes up the tree, while find looks for elements down the tree
var thisRadioName = $(this).find("input:radio").attr('name');
you can use also ':checked' to check if any radio is checked
var checkedRadio = $(this).find("input:radio:checked")
You should use children if you are absolutely sure that the elements you are looking for are direct child of the element, otherwise use find(). (using finds protect you from refactoring code if you modify the html, like adding a wrapping div for other reasons like styiling)
look at this fiddle: http://jsfiddle.net/nicolapeluchetti/Evq6y/
var thisRadioName = $(this).find("input:radio").attr('name');
should do what you want

Categories

Resources