I'm having trouble coming up with a way to show my "no results" div element. Basically, I have a list component containg order timeline section components, each one of these section contains order components. Like so:
My orders-list.component.html (check bottom div):
<div class="list-container" [ngClass]="{section: isDeliverySlotsActive === false}">
<label class="list-header" *ngIf="isDeliverySlotsActive === true" style="margin-top: 1.625rem">DELIVERY SLOTS ORDERS</label>
<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>
/* I want to show the below div when there are no results for the search */
<div id="no-results">
<img src="../../../assets/my-orders/no-results.png" alt="No Results" style="margin-top: 6.063rem; margin-bottom: 2.837rem;">
<label class="no-results-text">COULDN'T FIND ANYTHING</label>
<label class="no-results-text weight-medium">Search by order number or customer</label>
</div>
For each section, a filtering method is applied when the user searches for an order using the search bar. If the search term does not correspond to an order in a section, the order is not displayed for that section. If there are no results for that section the section header is also not displayed.
My orders-list-section.component.html:
<div *ngIf="filteredSectionOrders.length > 0">
<label
*ngIf="isDeliverySlotsActive === true"
[ngClass]="{ slots: isDeliverySlotsActive === true }">
{{ timeline | addSectionDateFormat }}
</label>
</div>
<div *ngFor="let order of filteredSectionOrders">
<app-orders-list-item
[order]="order"
[timeline]="timeline"
></app-orders-list-item>
</div>
My filter method in the section component:
filterSectionOrders(searchString: string){
if(!searchString) return;
if(this.hasNumbers(searchString)){
this.filteredSectionOrders = this.filteredSectionOrders.filter(order => order.order_num.toString().indexOf(searchString) !== -1);
}
else{
this.filteredSectionOrders = this.filteredSectionOrders.filter(order => {
if(order.first_name && order.last_name){
let fullName = order.first_name + " " + order.last_name;
if(fullName.toLowerCase().indexOf(searchString.toLowerCase()) !== -1){
return order;
}
}
})
}
}
Given that I apply this filter to each section and not to the list as a whole, how can I find out when there are 0 total results so I can show only one (not for each section) div element with a "no results found" message?
Thank you in advance.
You can easily use *ngIf;else link to ngIf from angular inside your HTML
I am not sure where do you use filteredSectionOrders, because it is not shown in your html, but let's assume your app-orders-list-section has some HTML logic where you use *ngFor to loop through orders and show it properly
so, I guess your code looks something like this
<div class="order" *ngFor="let order of filteredSectionOrders">
<img/>
<p>
{{ order.first_name + ' ' + order.last_name }}
</p>
</div>
This is simplified html how I assume it looks like.
What you can do is next:
<ng-template *ngIf="filteredSectionOrders.length > 0; else noResultsBlock">
// here you insert your code to render orders
<div class="order" *ngFor="let order of filteredSectionOrders">
<img/>
<p>
{{ order.first_name + ' ' + order.last_name }}
</p>
</div>
</ng-template>
<ng-template #noResultsBlock>
<p> No results </p>
</ng-template>
So, this would simple solution
If you want to improve it even more, it would be better to have a new variable, lets say areThereResults, which you will set to true or false, at the end of your method filterSectionOrders, based on filterSectionOrders.length. Then, you would use this new variable inside *ngIf check, instead of filterSectionOrders.length > 0.
Reason for using boolean variable instead of using actual array is detection changes, and will anguar re-render UI inside *ngIf. You can read more about it on Angular documentation, just search for detection changes.
I have a list of elements displayed on my HTML page. For whatever element selected, I wish to retrieve the corresponding data from the firebase database.
Here's the code of how I am displaying the list on the HTML page. These items are retrieved from firebase.
<div class="list-group " *ngFor="let year of years | async">
<a routerLink="records" routerLinkActive="active">
<mdb-icon fas icon="table" class="mr-3"></mdb-icon>{{year.key}}</a>
</div>
routerLink="records" , Records.html is where I would like to display the corresponding data.
Records is a html page where...based on the selected "year" , the data should be dynamically loaded.
I would use two services
one for your http calls (apiService) and one for storing the datas in your app (in that case dataService)
in your actual ts
years:any[] = []
//you can trigger that with ngOnInit or other events
this.apiService.getYears.subscribe(
data => {
this.dataService.setYears(data)
this.years = this.dataService.getYears();
}
)
in your html (no more async just data)
<div class="list-group " *ngFor="let year of years | async">
<a [routerLink]="['records/'+ year.key]" routerLinkActive="active">
<mdb-icon fas icon="table" class="mr-3"></mdb-icon>{{year.key}}</a>
</div>
then in your record component
year:any = undefined
//check for ActivatedRoute.params for retrieving the key (here `yearKey`) in your url
ngOnInit(){
if (!(this.year = this.dataService.getYear(yearKey)))
this.apiService.getYear(yearKey).subscribe(
data => this.year = data
)
}
REFERENCES
Services
I am currently trying to implement a selectable listview but am running into a few issues. I am trying to use ui-listview, an angular add-on of sorts, but want to (1) highlight the < p > tag that the user clicks on, and (2) get this string into an angular variable. Is there a way to do this, or a different implementation of a listview that allows this?
<div class="panel-body" padding:0>
<div class="ui-list-view-striped" ui-list-view="contact in contacts | orderBy:'Project' | filter:search">
<p class="name">{{ contact.ListView }}</p>
</div>
</div>
Can you modify the objects in your contacts list? If so, you can add a selected boolean attribute to them that can be fired by an ng-click event over every <p> element. Then you can use that selected attribute in an ng-class to set a style marking the element as selected. Ej:
html:
<div class="panel-body" padding:0>
<div class="ui-list-view-striped" ui-list-view="contact in contacts | orderBy:'Project' | filter:search">
<p class="name" ng-class="{'css-selected': contact.selected}">{{ contact.ListView }}</p>
</div>
</div>
javascript:
in your controller:
yourController.markSelected = function(contact) {
contacts.map(function(c) { c.selected = false; });
contact.selected = true;
}
css:
.css-selected {
/* your style for the selected element */
}
I'm new to AngularJS but I love the framework.
What I have right now, is a (stub) single page that loads json data.
JS
var merlinoApp = angular.module('merlino', []);
merlinoApp.controller('mainController', function ($scope, $http) {
...
$http.get('#Url.Action( "consoledatapull", "ConsoleElaborazioni")')
.then(function (res) {
$scope.jobs = res.data.jsonjobs;
$scope.clienti = res.data.jsonclienti;
$scope.console = res.data.jsonconsole;
});
...
});
HTML
<div ng-repeat="roll in jobs | orderBy:sortType:sortReverse | filter:searchJob | filter:searchCliente | filter:searchStato" class="console-row my-row">
...
<div class="console-cell-id console-cell console-cell-padding console-cell-no-border-sx">{{ roll.id }}</div>
...
<div ng-click="collapsed=!collapsed" ng-class="{'console-cell-esito-selected' : collapsed}" class="console-cell-esito console-cell console-cell-no-border-sx">SHORT DESC</div>
<div ng-show="collapsed" class="console-cell-esito-long console-cell console-cell-no-border-sx">{{ roll.esito }}</divng-show></div>
</div>
This populates ng-repeat, and the ng-click shows/hides the `ng-show div.
So far so good(?).
What Ì'm trying to achieve, is to load json data into
<div ng-show="collapsed" class="console-cell-esito-long...
if
<div ng-click="collapsed=!collapsed" ng-class="{'console-cell...
is clicked.
That is each div of ng-repeat, can be loaded with specific data:
<ul>
<li ng-repeat="logelem in jsonlog">
{{ logelem.log }}
</li>
</ul>
I thought about using a function:
<div ng-click="function(id)...
and then load json into a div identified by an id, so i used $index...
The result was, being able to load same data into all divs at once :/
Help would be appreciated.
My suggestion woudl be to add the information to the jobs elements itself.
So for example, the ng-click would become:
<div ng-click="loadData(id, roll)">CLICK ME</div>
and then the loadData would be something like:
$scope.loadData = function(id, roll){
// Do something
roll.result = result;
}
and then you can use the result from that object in the view like you would do in other places. You can then for example hide the object where you want the final result until the variable result is defined.
I think this will be the easiest solution.
Update from comments
Why not change the collapsed value in the method? Or you could use a $watch to listen to changes on the collapsed variable.
What I am trying to do is have a drop down menu divided. In this example there are Five Options how can I split the drop down into categories? For example option 1 and 2 pop out of the environment category and option 3 and 4 sports category and 5 college category? http://jsfiddle.net/fc3550sk/
For example:
Drop down: Please Select when you click it Menus will be Environment, Sports, Colleges..
Then hover over Environment and it will let you choose from option 1 or 2... or hover over sports and it will let you chose from 3 or 4 and so on..
This is what I have so far:
<select name="SPECIAL" id="SPECIAL">
<option>Please Select</div>
<option data-img="/images/img/AnimalFriend.png" value="1">AnimalFriend</option>
<option data-img="/images/img/Aquaculture.png" value="2">Aquaculture</option>
<option data-img="/images/img/ProtectOurOceans.png" value="3">Protect Our Oceans</option>
<option data-img="/images/img/ConserveWildlife.png" value="4">Conserve Wildlife</option>
</select>
<!-- Modal -->
<div class="modal fade" id="modal_special" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="myModalLabel">Specialty Plate</h4>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary accept">Accept</button>
</div>
</div>
</div>
</div>
$(function() {
$('#SPECIAL').on('change', function() {
if ($('option:selected', this).is('[data-img]')) {
$('#modal_special').find('.modal-body').html('<p>Image will go here:</p>')
.append('<img alt="coming soon" src="' + $('option:selected', this).data('img') + '"/>')
.end().modal('show');
}
});
$('.accept').on('click',function() {
//do something
$('#modal_special').modal('hide');
});
});
Any help would be greatly appreciated!!
I don't know of a way to attach a "hover" event listener to a standard drop-down menu, but it's not too much work to implement your own custom drop-down with jquery, html and css.
Custom Drop-down Advantage #01
You get to assign as many custom values to each entry as you want.
In your example, you have "Specialty Plates", and you may want to assign a price, a special code assigned to that plate, an image assigned to that plate, and so on. With an HTML/jQuery version, you can create your custom drop-downs with simple <span> tags like this:
<span data-code="SPRT01" data-image="" data-price="34.00">Sports 01</span>
<span data-code="SPRT02" data-image="" data-price="35.00">Sports 02</span>
<span data-code="SPRT03" data-image="" data-price="36.00">Sports 03</span>
Notice how each entry has three custom values assigned to it: data-code, data-image, and data-price. If you use an html drop-down, you don't have as much freedom. There are ways to extend the values associated with a standard drop-down, but getting at the values is messy, and you will still not have access to the hover behavior your features require.
Custom Drop-down Advantage #02
You can actually use the hover behavior in any way you want.
In your example, you want the "submenus" to show up when certain values in your drop-down are selected, but as far as I know, there isn't a way to gain access to the values that are "hovered" in a standard drop-down, and looking for an HTML-only solution just doesn't exist, so you would have to use javascript in one way or another.
Using jQuery, you can easily get to the values in your custom drop-down elements like this:
$("span").hover(
function(){
var text = $(this).text();
console.log("You have hovered on: ", text);
},
function(){
// You have hovered off the span
}
);
My Solution to Your Problem
Putting these ideas into practice, I put together a simple demo of how you can create a custom drop-down using your applications parameters.
You can review a jsfiddle of the demo here.
The Basic idea is that you create a hierarchy in html with the structure of your Top-level options (Environment, Sports, Colleges) in the div .drop_down_scroll_container, and you place all your sub-level divs (Environment 01, Environment 02, etc) below that div in a div classed .dropdown-subcategory. Where the magic happens, is that javascript looks up the index of the top-level option, and then reveals the dropdown-subcategory with that same index.
For example, in the following snippet of html, you can see the index positions of each of the spans within the drop_down_scroll_container div:
<div class="drop_down_scroll_container">
<span>Environment</span> <!-- index 0 -->
<span>Sports</span> <!-- index 1 -->
<span>Colleges</span> <!-- index 2 -->
</div>
So then, when you hover over any of those Top-level options (Environment, Sports, Colleges) you can ask jQuery to reveal the corresponding submenu div, which are sitting below the .drop_down_scroll_container div in div containers with a class of .dropdown-subcategory
<div id="dropdown" class="specialtyPlatesCategories">
<div class="selectHeader">Click to Select Plates:</div>
<!-- THIS IS WHERE YOU WILL PUT YOUR TOP-LEVEL OPTIONS -->
<div class="drop_down_scroll_container">
<span>Environment</span>
<span>Sports</span>
<span>Colleges</span>
</div>
<!-- THIS DIV IS AT INDEX 0 of: #dropdown.dropdown-subcategory -->
<!-- Will fade in when the drop_down_scroll_container index 0 is hovered -->
<div id="env_subcategories" class="dropdown-subcategory">
<span data-code="ENV01" data-image="" data-price="31.00">Environment 01</span>
<span data-code="ENV02" data-image="" data-price="32.00">Environment 02</span>
<span data-code="ENV03" data-image="" data-price="33.00">Environment 03</span>
</div>
<!-- THIS DIV IS AT INDEX 1 of: #dropdown.dropdown-subcategory -->
<!-- Will fade in when the drop_down_scroll_container index 1 is hovered -->
<div id="sports_subcategories" class="dropdown-subcategory">
<span data-code="SPRT01" data-image="" data-price="34.00">Sports 01</span>
<span data-code="SPRT02" data-image="" data-price="35.00">Sports 02</span>
<span data-code="SPRT03" data-image="" data-price="36.00">Sports 03</span>
</div>
<!-- THIS DIV IS AT INDEX 2 of: #dropdown.dropdown-subcategory -->
<!-- Will fade in when the drop_down_scroll_container index 2 is hovered -->
<div id="colleges_subcategories" class="dropdown-subcategory">
<span data-code="COLL01" data-image="" data-price="37.00">Colleges 01</span>
<span data-code="COLL02" data-image="" data-price="38.00">Colleges 02</span>
<span data-code="COLL03" data-image="" data-price="39.00">Colleges 03</span>
</div>
</div>
If none of that made any sense, here is another way of looking it at:
When the first item in the .drop_down_scroll_container is hovered, jQuery looks for the first instance of a .dropdown-subcategory below it. When the second item in the .drop_down_scroll_container is hovered, then jQuery will reveal the second instance of the .dropdown-subcategory, and so on. This lets you build as many options as you want, without having to worry about giving everything specific names, only the order matters in this case. So when the "Environment" option (who's index equals 0) is hovered, the .dropdown-subcategory with an index of 0 will show. That is the basic idea.
So now for the jQuery that puts it all together:
$(document).ready(function(){
// When the header for the custom drop-down is clicked
$(".selectHeader").click(function() {
// cache the actual dropdown scroll container
var dropdown = $(this).parent().find(".drop_down_scroll_container");
// Toggle the visibility on click
if (dropdown.is(":visible")) {
dropdown.slideUp();
$(this).parent().find(".dropdown-subcategory").fadeOut();
} else {
dropdown.slideDown();
}
});
// When a top-level menu item is hovered, decide if its
// coorespnding submenu should be visible or hidden
$(".drop_down_scroll_container span").hover(
// hover on
function() {
// Remove the "highlighted class from all other options
$(this).parent().find("span").removeClass("highlighted").removeClass("selected");
$(this).addClass("highlighted").addClass("selected");
// Get the index of the hovered span
var index = $(this).index();
// Use the hovered index to reveal the
// dropdown-subcategory of the same index
var subcategorydiv = $(this).parent().parent().find(".dropdown-subcategory").eq(index);
hideallSubmenusExceptMenuAtIndex($(this).parent().parent(), index);
subcategorydiv.slideDown();
},
// hover off
function() {
if (!$(this).hasClass("highlighted")) {
var index = $(this).index();
var subcategorydiv = $(this).parent().parent().find(".dropdown-subcategory").eq(index);
subcategorydiv.slideUp();
}
});
// Hide all submenu items except for the submenu item at _index
// This will hide any of the previously opened submenu items
function hideallSubmenusExceptMenuAtIndex(formElement, _index) {
formElement.find(".dropdown-subcategory").each(
function(index) {
if (_index != index) {
$(this).hide();
}
}
);
}
// When any menu item is hovered
$("span").hover(
function() {
$(".hoveredOver").text($(this).text());
},
function() {
$(".hoveredOver").text("");
}
);
// When a sub-menu option is clicked
$(".dropdown-subcategory span").click(function() {
$(".dropdown-subcategory span").removeClass("selected");
$(".clickedOption").text($(this).text());
$(this).addClass("selected");
$(this).parent().parent().find(".selectHeader").text($(this).text());
closeDropDown($(this).parent().parent());
showSpecialPlateModal($(this).text(), $(this).attr("data-image"), $(this).attr("data-price"), $(this).attr("data-code"));
});
// Close the dropdowns contained in divToSearch
function closeDropDown(divToSearch) {
divToSearch.find(".drop_down_scroll_container").fadeOut();
divToSearch.find(".dropdown-subcategory").fadeOut();
};
// Populate and Launch the bootstrap Modal Dialog Specialty Plates
function showSpecialPlateModal(name, image, price, code) {
$('#modal_special').find('.modal-body')
.html('<h2>' + name + '</h2>')
.append('<br/>Special Plate Code: <span class="code">' + code + '</span><br/>')
.append('<p>Image will go here:</p><br/><img alt="" src="' + image + '"/>')
.append('<br/><br/>Price: <span class="price">' + price + '</span><br/>')
.end().modal('show');
}
// When the modal "Accept" button is pressed
$('.accept').on('click', function() {
var modal_element = $('#modal_special');
var name = modal_element.find("h2").text();
var price = modal_element.find("span.price").text();
var code = modal_element.find("span.code").text();
$('#modal_special').modal('hide').end(alert(name + " was selected for a price of " + price));
});
});
Note: There may already be some open-source solutions that take care of this problem in a more elegant fashion. But this was my approach at solving an issue like this. As you can see, it only takes a little bit of setup to get going. You can easily control the styling of the drop-down in css, and you can extend this to do anything you want.
Again, you can review a jsfiddle to see all of this code in action here.
Hope this helps!
I am not sure if this is exactly what your were looking for but you could try something like this:
<select name="SPECIAL" id="SPECIAL">
<option>Please Select</div>
<optgroup label="Environmental">
<option
data-img="/images/img/AnimalFriend.png"
value="1">AnimalFriend</option>
<option
data-img="/images/img/Aquaculture.png"
value="2">Aquaculture</option>
</optgroup>
<optgroup label="Sports">
<option
data-img="/images/img/ProtectOurOceans.png"
value="3">Protect Our Oceans</option>
<option
data-img="/images/img/ConserveWildlife.png"
value="4">Conserve Wildlife</option>
</optgroup>
</select>