Ng-Repeat nested in ng-virtual-repeat isn't working - html

I'm working on a project for work where we display a dynamic table to a user. This table shows them a list of companies they are associated with, and the columns of that table can be specified by the user, where the columns correspond to properties of the company objects being displayed. Here is a snipped of my code:
<md-virtual-repeat-container id="vertical-container" style="height: 500px;">
<div md-virtual-repeat="company in companies" flex>
<div ng-repeat="filter in filters">{{::company[filter]}}</div>
</div>
</md-virtual-repeat-container>
Where filters is a list of columns the user wants to see. However, Angular is simply displaying nothing. I know that the data is there and I can display the data just fine if I don't use the virtual repeat, however there can potentially be 10k+ companies in the list, and eventually they will need to be data-bound, so the virtual repeat is almost necessary.
What am I doing wrong here? Is there a better way to implement a table in the manner I'm describing?
Also under consideration would be refactoring using React instead, would React be better equipped to build this kind of table?

Looks like it was the interaction between the repeat-container and the div that had the repeat directive on it. Replacing the div with an md-list-item resolved the issue.
<md-virtual-repeat-container id="vertical-container" style="height: 500px;">
<md-list-item md-virtual-repeat="company in companies" flex>
<div ng-repeat="filter in filters">{{::company[filter]}}</div>
</md-list-item>
</md-virtual-repeat-container>

Related

Angular infinite scrolling strategy with IntersectionObserver

I've been reading a lot about infinite scrolling strategies as I need to implement this functionality in my component. However, there seems to exist a lot of different approaches and the examples I've seen are not the most straight forward and easy to understand.
To put it briefly, this component consists of 3 mat-tabs (each represent a different order status), and inside each one of these there is a list of order components for that corresponding order status.
The smart parent component looks something like:
<mat-tab-group dynamicHeight animationDuration="400ms">
<mat-tab>
<app-orders-list
[orders]="loadedPendingOrders"
[timelines]="pendingOrderTimelines"
[isDeliverySlotsActive]="isDeliverySlotsActive"
[searchTerm]="searchTerm"
></app-orders-list>
</mat-tab>
...
/* more tabs */
</mat-tab-group>
And the child app-orders-list looks like this (each section contains orders):
<div class="list-container" [ngClass]="{section: isDeliverySlotsActive === false}">
<div [ngClass]="{section: isDeliverySlotsActive === true}" *ngFor="let date of timelines">
<app-orders-list-section
[orders]="orders"
[timeline]="date"
[isDeliverySlotsActive]="isDeliverySlotsActive"
[searchTerm]="searchTerm"
></app-orders-list-section>
</div>
</div>
When I reach the bottom of this list on a scroll down event, I need to load more orders from the API and present them accordingly.
Given this architecture, what strategy do you recommend for infinite scrolling? I'm mainly looking for something like a directive that implements the IntersectionObserver API and triggers an event when the bottom of the list is reached.
I'm not interested in solutions that use ngx-infinite-scrolling.
Thank you in advance.

In an Angular page containing custom components, how should I make sure all IDs are unique to get rid of the warnings?

I have a custom component for text input and each of them has an internal field ID'ed as data. It causes the warning below to appear.
[DOM] Found 13 elements with non-unique id #data
I'm clear on why it happens and I understand that's a warning not an actual error. I also recognize the appropriateness of an ID being unique (in its scope).
I'm not entirely sure regarding the implications in my particular case. In my opinion, warnings are tolerable but not acceptable.
Is there a best-practice approach to get rid of the error? By the very concept of a GP component, some parts will be alike in each instance. Or is there a trick to unique'fy the IDs? Or perhaps a directive or such to let Angular know we're cool with the state as is?
The component uses #ViewChild("data") to refer the input control in the template below.
<div id="outer">
...
<label for="data">{{label}}</label>
<input #data id="data" ... >
<div *ngFor="let error of errors" class="row"> ... </div>
</div>
As far as I understand the purpose of using ids is querying it inside of Angular. You could use a directive or another attribute to query without any warnings. Also you could make a kind of wrapper which would apply common ID to input and its label and just concat UUID and ID you want to use. But if it's only about querying just choose another attribute. For example data-id or data-qa whatever gives you an ability to query and have no errors at the same time. Just in case #ViewChild("data") refers to #data and not id="data" whilst you may wrap input with label tag.

How do I set AG-Grid's height to automatically match the data content height?

I'm trying to get ag-grid's height to match the content.
I have several sets of data which I'm trying to load into different grids, each with the appropriate height for the data.
There is an AutoHeight option but the Angular version doesn't seem to work (I'm assuming this is for a previous version).
Here is my alternative attempt, which doesn't work:
<ng-container *ngFor="let reportItem of reportData">
<br />
<ag-grid-angular style="width: 100%; height: {{ 560 + (reportItem.data.length * 40) }}px;"
class="ag-theme-material bold-headers"
[rowData]="reportItem.data"
[columnDefs]="columnDefs">
</ag-grid-angular>
</ng-container>
Does anyone have a better suggestion?
Rather than just linking to the Auto-Grid Height method I described at the top - which I tried and failed with, could you please explain how I should implement it with my code above? (as I accept I may have missed something)
Thanks
There is the setGridAutoHeight method available on the api object. You need to get a reference to that object from the gridReady event and then you can call it, passing true to it. You have to take care with it if your data has many rows because using this method all the rows will be rendered to the DOM, normally only the visible ones are rendered.
gridApi.setGridAutoHeight(true)
It's at the bottom of the page: https://www.ag-grid.com/javascript-grid-api/
according to this link you can use domLayout='autoHeight' as a property to your grid.
it worked for me.

Angular JS - Character counter across multiple text inputs

I have an Angular JS app I am building along with Angular-UI (bootstrap).
I have a set of multiple input boxes, which the user can input into and then that input is binded into a div. What I would like to do is have a character count that applies to all the boxes, so its one limit on all boxes and as the user types into them boxes the overall counter is affected. So far I can do this:
<p>xxxxxxxx?</p>
<textarea class="form-control" rows="3" ng-model="what[$index]" id="input" maxlength="200"></textarea>
<span>{{200 - what[$index].length}} left</span>
So this will give me a limit on that box, but how Can i get it so I have a overall counter? I have about 8 more text boxes and they are binded into a div as follows:
<div ng-repeat="w in what">
<p style="font-size:22px;"></p>
<p>{{w}}</p>
</div>
app.js
$scope.what=[];
Any help would be appreciated?
Two Way Data-Binding
First you need to set up 2 way data-binding so that when a user makes a change to the model it has an effect on the controller. you will use $scope for this since scope represents your model in Angular. then to build a running total I have 2 options for you.
Quick and Dirty
A quick and dirty way to count up a total across different controllers and other parts of your angular app would be to use $rootScope.YourCountVar. Root scope is a global variable and has its own host of problems because of this.
declare a counter near the top of your application (after angular.module) in app.js like this
.run(function ($rootScope) {
$rootScope.counter= 0;
})
Now in your controllers that you would like to count you need to set the value of $rootScope like
$rootScope.counter += $scope.YourInputData.length;
Repeat that for each of your inputs.
Best Practice
Create a Service that you can instantiate everywhere you need to add onto the running total. This way you only have the service where you need it. Doing things this way is much safer and cleaner and I would recommend it.

Generate different pages on the basis of different contents

Let me assume that I have the following architecture
_components (folders)
x1.html
x2.html
x3.html
I have a first page where I got the information from the YAM section for every component.
At this point I would like to add a link for every component to another page where I will display the component in a bigger manner.
So, let me assume I have, in the first page :
<div class="col-md-1">
<span id= "logos" class="material-icons"></span>
</div>
and In the componentbig.html I would like to open the right component on the basis of the link.
Do you have any suggestions for me ?
If I understand You correctly, then collections might be the feature You are looking for. For example, I'm usually using collections to generate a list of products and then have a specific page for each product also. Also make sure You check the easy tutorial by Ben Balter.