show item on specific table cell on hover in angular 4 - javascript

<td *ngFor="let tbh of tblH; let i=index" on-mouseover="hoveredI=i" on-
mouseleave="hoveredI=-1">{{data[tbh]}}
<div class="onHoverDiv" *ngIf="i==hoveredI">
<ul>
<li (click)="editCell(data,tbh);">
<span class="fa fa-pencil"></span>
</li>
</ul>
</div>
</td>
this my HTML code to show edit icon on hover on specific table cell but the problem is its working but its show icon in all the particular column of table cell i want show edit icon on hover in specific table cell how this to be done

Try with the following css:
li.fa-pencil {
display: none;
}
li:hover.fa-pencil {
display: inline-block;
}

you need to set one extra key is_hover into your array.set is_hover by default false.and just set below code.
you need to set like first in the component.
tblH.foreach((tbh,i)=>{tblh[i].is_hover = false})
html
<td *ngFor="let tbh of tblH; let i=index" (mouseleave)="tbh.is_hover =!tbh.is_hover" (mouseenter)="tbh.is_hover =!tbh.is_hover">{{data[tbh]}}
<div class="onHoverDiv" *ngIf="tbh.is_hover">
<ul>
<li (click)="editCell(data,tbh);">
<span class="fa fa-pencil"></span>
</li>
</ul>
</div>
</td>

Related

Dropdown menu click eventListener producing a different target element based on area clicked

I have a MaterializeCSS dropdown menu implemented with this HTML. The event listener works only if the dropdown item is clicked in the upper portion.
<div class="left">
<span id="notificationTotal" class="new badge red" style="display:none">
</span>
<a class="dropdown-trigger" href="#!" data-target="notificationsDropdown">
<i class="material-icons"> message</i>
</a>
</div>
<ul id="notificationsDropdown" class="dropdown-content">
</ul>
I'm using the following Javascript to populate the menu with notifications. This is working just fine.
// Reset Notification Dropdown
notificationsDropdown.innerHTML = '';
notifications.forEach(notif => {
const displayTime = moment(notif.date).fromNow();
let typeIcon = 'sms';
if (notif.type === 'chat') {
typeIcon = 'lock';
}
notificationsDropdown.innerHTML += `<li class="notification">
<a style="margin-top:0px;margin-bottom:0px;padding-bottom: 0;font-size:14px" href="#" class="blue-text">
<span class="js-patientName">
${notif.contact.firstName} ${notif.contact.lastName}</span>
<span class="js-notificationPhone" style="display:none">${
notif.contact.phone
}</span>
<span class="js-patientId" style="display:none">${
notif.patientId
}</span>
<span class="js-patientDOB" style="display:none">${
notif.contact.birthDate
}</span>
<p style="margin-top:0px;margin-bottom:0px;padding-bottom: 0;padding-top: 0;">
<i style="display: inline-flex; vertical-align:middle" class="tiny material-icons">${typeIcon}</i>
<span class="black-text" style="font-size:12px">
${displayTime}
</span>
</p>
</a></li>`;
});
notificationsDropdown.innerHTML += `<li class="divider" class="blue-text"></li><li>See All Notifications</li>`;
}
The dropdown gets populated and when a user clicks on a particular dropdown .li entry depending on the exact location they click, it may or not work. The user must click at the main top of the dropdown item.
This is the event listener code that extracts the values from the hidden span elements.
document
.querySelectorAll('#notificationsDropdown', '.li .a .notification')
.forEach(input =>
input.addEventListener('click', async e => {
// console.log('clicked', e.target);
console.log(e.target.parentNode);
const name = e.target.children[0].textContent.trim();
const phone = e.target.children[1].textContent.trim();
const patientId = e.target.children[2].textContent.trim();
const birthDate = e.target.children[3].textContent.trim();
console.log('patientid ', patientId);
const patient = {
name,
patientId,
phone,
birthDate
};
Is there a way I can rewrite the eventListener code to resolve this issue? Possibly instead of using e.target.children[insert_number_here].textContent I could use .closest('js-patientId') or similar ?
This is how the HTML is rendered to the page. This is an example of a single notification:
<ul
id="notificationsDropdown"
class="dropdown-content"
tabindex="0"
style="display: block; width: 177.297px; left: 1648.7px; top: 0px; height: 251px; transform-origin: 100% 0px; opacity: 1; transform: scaleX(1) scaleY(1);"
>
<li class="notification">
<a
style="margin-top:0px;margin-bottom:0px;padding-bottom: 0;font-size:14px"
href="#"
class="blue-text"
>
<span class="js-patientName">ANDREW TAYLOR</span>
<span class="js-notificationPhone" style="display:none">
5555551212
</span>
<span class="js-patientId" style="display:none">
1
</span>
<span class="js-patientDOB" style="display:none">
1960-01-01
</span>
<p style="margin-top:0px;margin-bottom:0px;padding-bottom: 0;padding-top: 0;">
<i
style="display: inline-flex; vertical-align:middle"
class="tiny material-icons"
>
sms
</i>
<span class="black-text" style="font-size:12px">
2 hours ago
</span>
</p>
</a>
</li>
<li class="divider" />
<li>
<a href="/notifications" class="blue-text">
See All Notifications
</a>
</li>
</ul>;
For dropdowns, the better way to handle actions is through onChange event. So you could attach your eventHandler on onChange of dropDown itself rather than attaching onClick on each of dropDown items. So whenever you change the selected value the onChange event will be triggered and you can easily get the selected value.
I was able to remove the in each li. Then adjust the value assignment to use the following:
e.target.parentNode.children[0].textContent.trim();

Semantic UI dropdown value getting retained, when the table row is deleted

A table is rendered with rows based on the values inside the array 'results'. There is a dropdown present in each of the row, which is populated via an array 'statuses'.
<div id="app">
<table>
<tr v-for="(row,index) of results">
<td>{{index}}</td>
<td>{{row.name}}</td>
<td>
<div :id="row.id"
class="ui selection dropdown status_dropdown">
<i class="dropdown icon"></i>
<div class="text">{{row.status}}</div>
<div class="menu">
<div class="item" v-for="status of statuses"
:data-index="index">
{{status.status}}
</div>
</div>
</div>
</td>
</tr>
</table>
</div>
Following is change dropdown function, which basically removes the row if the selected text in dropdown is "Delete":
$('.status_dropdown').dropdown({
onChange: function(value, text, $choice) {
let temp_index = $($choice).attr("data-index");
if(text === "Delete"){
vm.results.splice(temp_index,1);
}
}
});
Here's a codepen with complete code: https://codepen.io/anon/pen/KxzZOB
Now, if the status is changed to "Delete", although the row gets removed, the value of dropdown "Delete" is getting retained on that row.
To reproduce in the codepen sample, change the first row's status (index 0) to "Delete". You'll see that status for "Doe" appears as "Delete".
Also, if any of the dropdown value is changed. And some other row's dropdown value is changed, the previous row for which the status was changed retains the value.
To reproduce in the codepen sample, reload the page. Now, change the status for third row (index 2) to "Active". Now delete the second row (index 1) by selecting "Delete". You'll see last row retaining the value "Active".
Can someone help me out with this issue?
To resolve this issue, you can define the key. see below:
<div id="app">
<table>
<tr v-for="(row,index) of results">
<td>{{index}}</td>
<td>{{row.name}}</td>
<td>
<div :id="row.id"
:key="row.id"
class="ui selection dropdown status_dropdown">
<i class="dropdown icon"></i>
<div class="text">{{row.status}}</div>
<div class="menu">
<div class="item" v-for="status of statuses"
:data-index="index">
{{status.status}}
</div>
</div>
</div>
</td>
</tr>
</table>
</div>
Defining the key should maintain the dom item instance while it moves within the table.

Knockout JS - Setting table width based on an observable field

I am building a web page with a table showing transactions.
The table has a drop-down menu which is used to select the transaction type to display. A table with one row contains this drop-down menu, which needs to be aligned to show at the right edge of the transaction table. Other filter fields are present, depending on the transaction type, and these start from the left side of the table's single row.
Depending on the transaction type, the table's width changes.
I created an observable field in my view model which equals the current width of the table.
The following markup defines this layout, with only one filter - the dropdown selection of transaction type.
<fieldset id="transactionFilters">
<table data-bind="width: TransactionGridWidth">
<!-- I also tried the following:
<table data-bind="style: {width: TransactionGridWidth}">
I tried appending "px" to the width field as well, with no change.
-->
<tr>
<th style="width: 350px">
<div class="dropdown" style="margin: 10px 0 10px 15px">
<div align="right">
<span style="padding: 10px">View </span>
<button class="btn btn-default btn-sm dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="true">
<span id="dropdownTitle" >Type 1</span>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li role="presentation"><a role="menuitem" tabindex="-1" href="#">Type 1</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="#">Type 2</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="#">Type 3</a></li>
</ul>
</div>
</div>
</th>
</tr>
</table>
</fieldset>
One of the following grids will be shown at a time, each with a different width:
<div id="type1TransactionsGrid" style="width: 1000px;"></div>
<div id="type2TransactionsGrid" style="width: 800px; display: none;"></div>
<div id="type3TransactionsGrid" style="width: 1200px; display: none;"></div>
The following KnockoutJS script defines the observable:
var ViewModel = {
Type1TransactionsGrid: ko.observable(),
Type2TransactionsGrid: ko.observable(),
Type3TransactionsGrid: ko.observable(),
TransactionGridWidth: ko.observable(),
OnLoad: function () {
ViewModel.TransactionGridWidth(1000);//initialisation
}
};
...//rest of the implementation
ko.applyBindings(ViewModel);
ViewModel.OnLoad();
I've got a switch-case which selects which transaction grid to display, and sets TransactionGridWidth to the current grid width, like so:
ViewModel.TransactionGridWidth(document.getElementById('Type1TransactionsGrid')).getBoundingClientRect().width);
I am certain this works, as I show the value of the field on-screen, and it tracks changes. The debugger confirms that the observable holds the correct width of the transaction grid.
No matter what I do, I can't get the table's width to change with the observable value. It works if I put in explicit size, e.g.
<table width="1000px">
TLDR:
I've got an observable variable which successfully tracks the width of the currently displayed transaction grid, but data-binding this variable to my filter table's style does not work.
What am I doing wrong?
It definitely works to use the style binding to set the width of a table. My guess is that there is some part of it you're doing wrong, but it's not clear from your question what that is.
function ViewModel() {
this.tableWidth = ko.observable();
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table style="border: 1px solid black" data-bind="style: {width: tableWidth() + 'px'}">
<tr>
<td>Some content</td>
</tr>
</table>
<p>
<select data-bind="value: tableWidth, options: [200, 300, 400]"></select>
</p>

Odd Angular/Bootstrap Dropdown Behavior

I've got an application requiring a series of dropdowns. The functionality requires me to be able to switch between normal dropdown behavior and multi-select behavior.
I have made slight modifications to the ui.boostrap.dropdown from the Angular Directives for Bootstrap (see Dropdown). Everything works well, except for a gray bar after clicking (looks like the :hover css stays active after clicking) when in Multiselect mode.
When I toggle off then back on, the highlight goes away, as if the hover event has somehow completed.
Process:
Open the dropdown
Click Multiselect
Move the mouse and Multiselect stays highlighted, as if the ":focus" tag is not removed.
Visually:
The mouse is over 345 in this image, Multiselect should not be highlighted.
Angular HTML for dropdown:
<div ng-controller="DropdownCompanyController as vm">
<div class="btn-group u-front_dropdown-wide" dropdown is-open="vm.isopen">
<button type="button" class="btn btn-default dropdown-toggle" dropdown-toggle>
{{ vm.selected }} <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" ng-click="vm.checkMultiSelect($event)">
<li ng-repeat="company in vm.companies"
ng-class="{ selected : company.selected }">
{{ company.name }}
</li>
<li class="divider"></li>
<li class="ng-scope" ng-class="{selected : vm.multi.select }">
<a href="#"
ng-click="vm.event.multiselect()"
ng-class="{ multi: vm.multi.select }">Multiselect</a>
<button
ng-hide="!vm.multi.select"
ng-class="{ multi_button: vm.multi.select }"
ng-click="vm.event.close_dropdown($event)">Close</button>
</li>
</ul>
</div>
</div>
Here's the event where the click on an element is handled:
vm.event = {};
vm.event.select = function(company) {
if (!vm.multi.select) {
clearCompanies(false);
company.selected = true;
vm.selected = company.name;
vm.isopen = false;
} else {
if (company.name !== vm.defaultCompany) {
company.selected = !company.selected;
vm.selected = vm.multi.title + countCompanies();
}
}
};
Link to Plunker.
I have had no luck tracking this down and my instinct is that the issue is in the CSS, but it's standard bootstrap CSS. Any assistance would be appreciated.
If you just dont want any item to have the highlight then in your own custom app.css file override the focus state with white:
.dropdown-menu > li > a:focus {
background-color: white;
}
Without doing a custom bootstrap build just add the hover following the focus to to keep the grey highlight:
.dropdown-menu > li > a:hover {
background-color: lightgray;
}

How to assign alternate class to rows in Angular JS?

I want to assign alternate class to rows in a table. I am using ng-repeat on
<tr ng-repeat="event in events">
I want to get output like this:
<tr class="odd">...</tr>
<tr class="event">....</tr>
I've tried this (doesn't work):
<tr ng-repeat="event in events" class="$index % 2 == 0? 'event' : 'odd'">
I can't get it to work. Also it seems like Angular is using 'class' attribute to. Why is it doing so? Can I tell AngularJS not to use the class attribute for internal evaluations?
Please help. Thanks!
You should be using the angular directives ngClassEven and ngClassOdd for this.
Have a look at the documentation section for how to use them
http://docs.angularjs.org/api/ng.directive:ngClassEven
http://docs.angularjs.org/api/ng.directive:ngClassOdd
From the Angular docs..
Use ng-class-odd ng-class-even
<li ng-repeat="name in names">
<span ng-class-odd="'odd'" ng-class-even="'even'">
{{name}}
</span>
</li>
As #ganaraj states ng-class-odd and ng-class-even are the right way to do this, but for the benefit of searchers, your initial proposal wasn't far off working in Angular >=1.2.19.
Here is a closely related example of something that would have worked and would also work if coloring more than alternate rows (e.g. every 3 rows):
<div>
<style>
.color0 {
background-color: lightblue;
}
.color1 {
background-color: lightyellow;
}
.color2 {
background-color: lightgray;
}
</style>
<div ng-repeat="result in results" ng-class="'color' + ($index % 3)">
<div>
<p>{{result.myText}}</p>
</div>
</div>
You can also use the ng-class-odd and ng-class-even directives directly within the ng-repeat directive.
<div class="cssOneProductRecord"
ng-repeat='..'
ng-class-odd="'cssProductOdd'"
ng-class-even="'cssProductEven'" >
Which gives us nice alternating classes for each row:
This example is taken from the following page, which also demonstrates how to turn JSON data into a friendly, responsive Master-View page:
Master-Views using AngularJS
Improving Fintan Kearney's answer,
From: https://docs.angularjs.org/api/ng/directive/ngClassOdd
Style.css
.odd {
color: red;
}
.even {
color: blue;
}
index.html
<ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
<li ng-repeat="name in names">
<span ng-class-odd="'odd'" ng-class-even="'even'">
{{name}}
</span>
</li>
</ol>

Categories

Resources