HostListner with particular element in the template Angular4? - javascript

My requirement is I want to fix the table header after certain scroll to up,while the table body is scrolling.
My app.html is below.
<table class="table table-fixed-ok" #scroller [class.fixed]="fixed">
<thead >
<tr class="row-hor-heading">
<th colspan="3" scope="row"><span class="bank-name">
{{offer.name}}</span>
</tr>
</thead>
<tbody>
<tr class="row-2-data bg-white">
</tr>
</tbody>
</table>
So i want to listen the scroll of this table only(app.html contains many more other div.i want this div scroll to be listened.)
My app.ts section is below
#HostListener('window:scroll', ['$event'])
onWindowScroll(event: Event) {
debugger;
let num = this.el.nativeElement.querySelector('.table-fixed-ok').scrollTop;
if ( num >50 ) {
this.fixed = true;
}else if (this.fixed && num < 5) {
this.fixed = false;
}
}
But this is not working as i needed.While printing the num variable always giving 0.And also it is triggering whole whole body scrolling.How to solve this.Please give me a solution.

There is no way to specify an element for #HostListener(), but you can just apply the event binding to the element directly like:
<div (scroll)="myScrollHandler($event)"

Related

Create a function that follows a moving text on a table

I found a function to move data between table cells but the functions never seem to stick to whatever tag is "attached" to the cell itself. I'm not sure if I was using ids wrong. I need help finding a way to "attach" a function to a tag that moves between cells.
Can you help me create a button to move a tag (unit 1) upwards and downwards through a table such that it stops at the end of the table?
Original code attached here
//Send to the "bottom"
function sendOS() {
var node = document.getElementById("r1c1").lastChild;
document.getElementById("r1c3").appendChild(node);
/*
var node = document.getElementById("r1c3").lastChild;
document.getElementById("r1c2").appendChild(node);
*/
}
//Send to the "top"
function sendTop() {
var node = document.getElementById("r1c2").lastChild;
document.getElementById("r1c1").appendChild(node);
}
table,
th,
td {
border: 1px solid black;
width: 32px;
height: 32px;
}
<table>
<tr id="row1">
<td id="r1c1">Unit1</th>
<td id="r1c2">Unit2</th>
<td id="r1c3">Unit3</th>
</tr>
<tr id="row2">
<td id="r2c1">r1c2</td>
<td id="r2c2">r2c2</td>
<td id="r2c2">r2c3</td>
</tr>
<tr id="row3">
<td id="r2c2">r3c1</td>
<td id="r2c2">r3c2</td>
<td id="r2c2">r3c3</td>
</tr>
</table>
<!--Table ends -->
<!-------------------------------------------------------------->
<button onclick="sendOS()">move to the other side</button>
<button onclick="sendTop()">move to the right</button>
I can't help you with creating all that. You should try it out for yourself, you'll learn a lot more.
But I can help you with the code you provided.
A lot of your id attributes are the same. Every id on the page should be unique.
Change your HTML structure slightly by adding a <span> around the texts inside your cells (<td><span id="target-1">Text</span></td>). That way you can select elements inside your cells and move those around. Using lastChild to get the TextNode is not the right approach.
The functions should check if there is a cell next to it in the direction you want to move the text. If there is, move the text. If not, then do nothing.
Below I've made a small demonstration on how this might work. Here target is the element that we move. It's the <span id="target">Foo</span> element in the HTML.
When clicking either button, the code will go one element up from the target element with parentElement, that will be the <td> our target is in.
It then tries to access the previous or next <td> in the row (depending on the direction). If a neighbouring <td> is found, it will append the element.
The advantage of this approach is that you always have a reference to the element that you are moving.
const target = document.querySelector('#target');
const buttonLeft = document.querySelector('.js-target-move-left');
const buttonRight = document.querySelector('.js-target-move-right');
function targetMoveLeft() {
const previousCell = target.parentElement.previousElementSibling;
if (previousCell) {
previousCell.append(target);
}
}
function targetMoveRight() {
const nextCell = target.parentElement.nextElementSibling;
if (nextCell) {
nextCell.append(target);
}
}
buttonLeft.addEventListener('click', targetMoveLeft);
buttonRight.addEventListener('click', targetMoveRight);
<table>
<tbody>
<tr>
<td><span id="target">Foo</span></td>
<td><span>Bar</span></td>
<td><span>Baz</span></td>
</tbody>
</table>
<button class="js-target-move-left">Left</button>
<button class="js-target-move-right">Right</button>
I hope this will at least push you in the right direction. Good luck with implementing the other features.

How can i add horizontal scrollbar on top and bottom of md-table?

I have implemented a horizontal scrollbar on the top and bottom of the table but I could see only the bottom scrollbar. But I would like this scrollbar to be also on top of the table.
I have used jquery code for scrolling and directive for the table.
Expected :
Currently, I See Only the bottom bar
demo
Demo you can see working code
angular.module('components', [])
.directive('master',function () { //declaration
function link(scope, element, attrs) {
scope.$watch(function(){
scope.duelScroll = {
width:element[0].offsetWidth+'px'
};
});
}
return {
restrict: 'AE',
link: link
};
})
angular.module("datatable", ['ngRoute', 'ngMaterial', 'md.data.table']).controller("datacontroller", ['$scope', function($scope) {
$(function () {
$("[name='upperScroll']").scroll(function () {
$("[name='wireTable']").scrollLeft($("[name='upperScroll']").scrollLeft());
});
$("[name='wireTable']").scroll(function () {
$("[name='upperScroll']").scrollLeft($("[name='wireTable']").scrollLeft());
});
$("[name='upperScroll']").css({ 'height': ($("[name='wireTable']").height() + 'px') });
});
$scope.DataSet = [1];
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.17/angular.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.12/angular-material.min.css">
<div ng-app="datatable" ng-controller="datacontroller">
<form name="Information">
<md-content layout-padding ng-repeat="Data in DataSet">
<ng-form name="invoice{{$index}}">
<md-card style="background-color:Gainsboro">
<div ng-init="isShowAll =true" ng-show="isShowAll">
<md-card>
<div name="upperScroll" style="overflow-x:scroll; overflow-y: hidden; max-height:20px; width:100%">
<div name="innerScroll" ng-style="duelScroll" style="height:20px;"></div>
</div>
<div ng-style="getStyle($index)">
<md-table-container name="wireTable" infinite-scroll="loadMore($index)" infinite-scroll-distance="1" infinite-scroll-parent="true" ng-init="isShow=true" ng-show="isShow">
<table master md-table md-progress="aPromise" name="innerWireTable">
<thead md-head md-order="sortOrder" style="background-color:#e0dcff; ">
<tr md-row style="height:45px">
<th md-column><span>Test1</span></th>
<th md-column><span>Test2</span></th>
<th md-column><span>Test3</span></th>
<th md-column><span>Test4</span></th>
<th md-column><span>Test5</span></th>
<th md-column><span>Test6</span></th>
<th md-column><span>Test7</span></th>
<th md-column><span>Test8</span></th>
<th md-column><span>Test9</span></th>
<th md-column><span>Test10</span></th>
<th md-column><span>Test11</span></th>
<th md-column><span>Test12</span></th>
<th md-column><span>Test13</span></th>
<th md-column><span>Test14</span></th>
<th md-column><span>Test15</span></th>
<th md-column><span>Test16</span></th>
<th md-column><span>Test17</span></th>
<th md-column><span>Test18</span></th>
<th md-column><span>Test19</span></th>
<th md-column><span>Test20</span></th>
</tr>
</thead>
<tbody>
<tr>
<td md-cell>Test1</td>
<td md-cell>Test2</td>
<td md-cell>Test3</td>
<td md-cell>Test4</td>
<td md-cell>Test5</td>
<td md-cell>Test6</td>
<td md-cell>Test7</td>
<td md-cell>Test8</td>
<td md-cell>Test9</td>
<td md-cell>Test10</td>
<td md-cell>Test11</td>
<td md-cell>Test12</td>
<td md-cell>Test13</td>
<td md-cell>Test14</td>
<td md-cell>Test15</td>
<td md-cell>Test16</td>
<td md-cell>Test17</td>
<td md-cell>Test18</td>
<td md-cell>Test19</td>
<td md-cell>Test20</td>
</tr>
</tbody>
</table>
</md-table-container>
</div>
</md-card>
</div>
</md-card>
</ng-form>
</md-content>
</form>
</div>
someone help me with this
I have already checked some questions related to the scrolling bar but I want to fix this code so please someone help me here to fix this issue
also, it should support scrolling if we have multiple table http://jsfiddle.net/e1w0vmns/1/
Made few changes to your code.
Added unique class based on ng-repeat index to div upperScroll
class="upperScroll{{$index+1}}" custom-index="{{$index+1}}"
Added similar class to wireTable
class="wireTable{{$index+1}}" custom-index="{{$index+1}}"
Updated the script to use those classes to make specific target to support multiple table scroll
$("[name='upperScroll']").scroll(function () {
var upperIndex = $(this).attr('custom-index');
$(".wireTable"+upperIndex).scrollLeft($(this).scrollLeft());
});
$("[name='wireTable']").scroll(function () {
var wireIndex = $(this).attr('custom-index');
$(".upperScroll"+wireIndex).scrollLeft($(this).scrollLeft());
});
Jsfiddle - http://jsfiddle.net/7t9pmkqa/
I'm not very much familiar with angular but going through the demo, I found the issue is with the width of innerScroll. You just need to set that width equal to table width
$("[name='innerScroll']").width($("[name='innerWireTable']").width());
You can find the working demo here
working demo
Did you try CSS overflow property?
overflow: scroll; /* Scrollbar are always visible /
overflow: auto; / Scrollbar is displayed as it's needed */
How to use it:
To use this plugin, just include the main JavaScript file jquery.doubleScroll.js after jQuery library:
<script src="//code.jquery.com/jquery.min.js">
<script src="jquery.doubleScroll.js">
Then call the function doubleScroll() on the scrollable container and done.
$('.element').doubleScroll();
Recompute the top ScrollBar requirements when the window is resized.
$('.element').doubleScroll({
resetOnWindowResize:true
});
Set the time to wait for the last update event (useful when browser fires resize event constantly during resizing):
$('.element').doubleScroll({timeToWaitForResize: 30});
Hide the top scrollbar if the bottom one is not present.
$('.element').doubleScroll({onlyIfScroll:true});
Override the default CSS styles:
$('.element').doubleScroll({
scrollCss:
{'overflow-x':'auto','overflow-y':'hidden'},
contentCss:
{'overflow-x':'auto','overflow-y':'hidden'},
});
Specify the element to use as the scroll reference. First child element is used if nothing is specified.
view source
$('.element').doubleScroll({
contentElement: undefined
});

Scroll should not go to the bottom while data change

In My angularJs application, I have a problem with scroll bar. There is a pop up which show a list of data in it and I refresh that data after every 5 seconds, by calling my API service in every 5 seconds.
Problem is that after refresh, side scroll bar goes automatically to the bottom. I google for that but dn't get satisfied solution, I used $anchorScroll in my config file which is not help full as well.
I am using Angular Material's md-dialog-content for popup list.
<md-dialog-content>
<div layout="row">
<div class="simple-table-container" flex>
<table class="simple" ms-responsive-table>
<thead>
<tr>
<th>ProcessItem</th>
<th>ElapsedTime</th>
<th>Status</th>
</tr>
</thead>
<tfoot>
<tr>
<td></td>
</tr>
</tfoot>
<tbody>
<tr ng-repeat="info in vm.process.data">
<td>{{info.item}}</td>
<td>{{info.time}}</td>
<td>{{info.Status}}</td>
</tr>
</tbody>
</table>
</div>
</div>
vm.process.processInterval = $interval(function () {
api.getdata.get({ 'ID': id },
function (response) {
if (response.data[0].hdata[0].pdata)
vm.process.data = response.data[0].hdata[0].pdata;
$scope.$watch(
"vm.process.data",
function (newObj, oldObj) {
if (newObj !== oldObj) {
vm.process.data = newObj;
}
}, true
);
},
function (response) {
console.error(response);
}
);
}, 5000);
Any Idea guys?
As I understand after ajax update page your scroll position not change. This is normal situation and in this case you should manual trigger scroll top to element that you want: element.scrollTop = pixels.
In other case you have some hash in url that trigger scroll to bottom element. And in this case you should clear it.

Appending a table to another table in the DOM. Targeting with no class or id available

I am currently attempting to append a specific , via jquery, to another table. Here's the HTML, and the two elements involved in the move.
<div id="content_area">
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr><td></td></tr>
<tr>
<td></td> <-- TD needing to move -->
</tr>
</tbody>
</table> <-- Needs to move-->
<table width="100%" cellspacing="0" cellpadding="5" border="0">
<tbody>
<tr>
<td width="190" valign="top">
<table width="100%"></table>
<-- Move Above TD Here -->
</td>
</tr>
</tbody>
</table>
</div>
Although I'm hardly experienced with jquery/javascript, I have used the following method in the past to append a div to another div.
$(".target").appendTo($(".destination"));
This method I have used in the past required that the elements have some sort of unique identification. Since this is not possible with the current site I am developing (The software has locked down the HTML), how can I target these two tables in order to make the append?
You can view the issue at the following page:
http://xlevj.jyetp.servertrust.com/Pro-Audio-Equipment-s/1824.htm
It's pretty obvious to see on that page what I'm trying to accomplish with the move. Thanks for any help!
Try this:
//Find the td we want to move.
var tdToMove = $('#divWaitModal + table > tbody > tr:nth-child(2) td');
//Find the td we want to insert into after.
var tdToInsertAfter = $('#divWaitModal + table + table tr:first-child td:first-child');
//Detach the td to move.
tdToMove.detach();
//Insert it at the proper place.
tdToInsertAfter.after(tdToMove);
Just use child number of the node and target trough that :
$('body table:first-child').appendTo( $('table:eq(1) td:eq(0)') );
In words it takes the first table and it's appending it to second table > first cell. You can use :eq( number ) where number starts from 0, or first-child selector in some cases ..
This CSS might accomplish what you're after:
#content_area {
overflow: hidden;
}
#content_area table {
display: inline;
float: left;
}
If you want to target the elements, you can use the #content_area as a selector:
var $tables = $('#content_area>table');
var $table1 = $(tables[0]);
var $table2 = $(tables[1]);

Simple setting off display: none / block with javascript

I have the following Code:
<table>
<tr class="odd"><td>Entry 1</td></tr>
<tr class="even clickable" onclick="showHide('sub2')"><td>> Entry 2</td></tr>
<tr class="even" id="sub2">
<td><ul><li>Information 1</li><li>Information 2</li></ul></td>
</tr>
<tr class="odd"><td>Entry 3</td></tr>
<tr class="even"><td>Entry 4</td></tr>
</table>
and the following js:
function showHide(id) {
var el = document.getElementById(id);
if( el && el.style.display == 'none')
el.style.display = 'block';
else
el.style.display = 'none';
}
with this css:
tr.odd{
background-color: #dedede;
}
tr.even{
background-color: #7ea9ff;
}
tr.clickable{
cursor: pointer;
}
tr.clickable:hover{
color: white;
}
tr[id^="sub"]{
display: none;
}
Could someone please tell me, why it doesn't work? I'm trying to show / hide onclick the row with the id="sub2"
example in jsfiddle
Open your debug console when you run your code, and you will get the message "ReferenceError: showHide is not defined".
If you place your html and javascript inside a file and run that that particular issue is resolved. It has something to do with the order with which jsfiddle processes sources.
Secondly, you are trying to get an element by id, but give it the class name - that does not make sense. By giving elements id's and using that it works.
But this is very unwieldy, and just serves to explain why it did not work. You are better off using jQuery as raphael said.
edit: replaced html with link
function showHide(id) {
var el = document.getElementById(id);
if( el && el.style.display == 'block')
el.style.display = 'none';
else
el.style.display = 'block';
}
First of all, in your JSFiddle example, the function is wrapped into a domready event. You should change the wrap of your JavaScript to No wrap - in body. This can be set up in the second dropdown in the left bar. Your function won't be accessible otherwise.
Then, the second line in your JavaScript searches for an element with an ID - but your document does not contain any ID's, it contains classes. document.getElementById can only find elements by their IDs.
I would suggest that you use jQuery for this task. With jQuery, the task can be solved like this:
HTML:
<table>
<tr class="odd"><td>Product 1</td></tr>
<tr class="trigger"><td>> Product 2</td></tr>
<tr class="even"><td> Information 1</td></tr>
<tr class="even"><td> Information 2</td></tr>
<tr class="odd"><td>Product 3</td></tr>
<tr class="even"><td>Product 4</td></tr>
</table>
JavaScript:
$(document).ready(function() {
$(".trigger").click(function() {
$(".even").toggle();
});
});
JSFiddle
jQuery Toggle Documentation
I don't know to explain to you why this is happening, but you need to check if css display property is set to none or it is empty. So this will trigger your function from the first time, otherwise it will go to "else", and then trigger on the next click.
So you need to check the following conditions:
if( el && el.style.display === 'none' || el.style.display === '')

Categories