muddatagrid - access filtered records programmatically - mudblazor

I have a muddatagrid like this which has got the filters and i am able to filter it. Programmatically how can I get the filtered records?
<MudDataGrid Items="#Elements" #ref="dg" Filterable="true" FilterCaseSensitivity=DataGridFilterCaseSensitivity.CaseInsensitive>
<Columns>
<Column T="RequestInfo" Field="RequestId" Title="Request ID" />
<Column T="RequestInfo" Field="ProjectName" Title="Project Name" />
<Column T="RequestInfo" Field="RequestCreatedBy" Title="Created By" />
</Columns>
<NoRecordsContent>
<MudText>No matching records found</MudText>
</NoRecordsContent>
<PagerContent>
<MudDataGridPager T="RequestInfo" />
</PagerContent>
</MudDataGrid>
#code
{
MudDataGrid<RequestInfo> dg;
private async Task somefunction()
{
//this function is invoked after pressing a button in the page and all the filters have been applied.
List<RequestInfo> ll = dg.FilteredItems as List<RequestInfo>;
}
}
This function returns always 0 items. How Do I get to see only the filtered items programmatically?

dg.FilteredItems probably isn't a List when you apply filters. Instead of ... as List<RequestInfo>, call .ToList() on it:
#code
{
MudDataGrid<RequestInfo> dg;
private async Task somefunction()
{
List<RequestInfo> ll = dg.FilteredItems.ToList();
...
}
}
whats the difference between dg.FilteredItems.ToList(); and dg.FilteredItems as List;
The code:
dg.FilteredItems as List<RequestInfo>
is equivalent to:
dg.FilteredItems is List<RequestInfo>
? (List<RequestInfo>)dg.FilteredItems
: (List<RequestInfo>)null
This means that if the IEnumerable dg.FilteredItems is not a List, null will be returned.
The code:
dg.FilteredItems.ToList()
will return a new List, no matter what IEnumerable dg.FilteredItems behind the scenes is (an array, a IList, a ISet, ...)

Related

How to sort a list that will be localized in JSF output

In my application I have a list of keys (strings), where the user can select one of them. In the user-interface, the keys will be output according to the current locale:
<h:selectOneMenu value="#{bean.selectedKey}">
<f:selectItems value="#{bean.allKeys}" var="_key" itemLabel="#{msgs[_key]}" />
</h:selectOneMenu>
My setup uses a standard resource-bundle configured in faces-config.xml as explained in this answer by BalusC. msgs in the example above is the name of the resource-bundle variable.
What I want now, is the items from the selectOneMenu to be sorted in alphabetic order. Of course the order depends on the used locale. The problem is, I can't/won't do the sorting in the backing-bean, as I don't know how the JSF-page will output the keys.
This problem seems quite generic to me, so I'm wondering what the best practice is to solve this kind of problem.
(Of course the problem is not only applicable to selectOneMenu. Any list/collection that will be output in the user-interface suffers from the same problem.)
You've basically 2 options.
Sort in client side with a little help of JS. I'll for simplicity assume that you're using jQuery.
<h:selectOneMenu ... styleClass="ordered">
$("select.ordered").each(function(index, select) {
var $select = $(select);
$select.find("option").sort(function(left, right) {
return left.text == right.text ? 0 : left.text < right.text ? -1 : 1;
}).appendTo($select);
if (!$select.find("option[selected]").length) {
select.options.selectedIndex = 0;
}
});
Sort in server side wherein you create List<SelectItem> and grab #{msgs} via injection. Assuming that you're using CDI and thus can't use #ManagedProperty("#{msgs}"), you'd need to create a producer for that first. I'll for simplicity assume that you're using OmniFaces (which is also confirmed based on your question history).
public class BundleProducer {
#Produces
public PropertyResourceBundle getBundle() {
return Faces.evaluateExpressionGet("#{msgs}");
}
}
Then you can make use of it as follows in the backing bean associated with <f:selectItems value>:
private static final Comparator<SelectItem> SORT_SELECTITEM_BY_LABEL = new Comparator<SelectItem>() {
#Override
public int compare(SelectItem left, SelectItem right) {
return left.getLabel().compareTo(right.getLabel());
}
};
private List<SelectItem> allKeys;
#Inject
private PropertyResourceBundle msgs;
#PostConstruct
public void init() {
allKeys = new ArrayList<>();
for (String key : keys) {
allKeys.add(new SelectItem(key, msgs.getString(key)));
}
Collections.sort(allKeys, SORT_SELECTITEM_BY_LABEL);
}
And reference it directly without var as follows:
<f:selectItems value="#{bean.allKeys}" />

HQL and Session.Query ignores eager fetching defined in mapping

I have a problem with NHibernate not using my mappings configuration for eager loading a collection when I get something using HQL or Linq (Session.Query). Session.Get and Session.QueryOver is working like expected.
I'm using NHibernate 3.2. Here's the mapping of a collection in my Product mapping.
<bag name="OrderItems" inverse="true" cascade="none" lazy="false" fetch="join">
<key column="order_id" />
<one-to-many class="OrderItem" />
</bag>
and from the other side the mapping looks like this:
<many-to-one name="Product" class="Product" column="product_id" not-null="true" />
I have 4 Tests, 2 are successfull and 2 are not. They use Session.SessionFactory.Statistics to keep track of CollectionFetchCount (was OrderItems selected in 1 joined query or in a separate). The intent is to have OrderItems selected and loaded when selecting the product as OrderItems are almost always accessed as well.
LastCreated is a simple reference to the last product inserted into the DB.
[Test] /* Success */
public void Accessing_Collection_Using_Session_Get_Results_In_1_Select()
{
// Get by Id
var product = Session.Get<Product>(LastCreated.Id);
var count = product.OrderItems.Count;
Assert.AreEqual(0,statistics.CollectionFetchCount,"Product collectionfetchcount using Get");
}
[Test] /* Success */
public void Accessing_Collection_Using_Session_QueryOver_Results_In_1_Select()
{
// Get by Id
var product = Session.QueryOver<Product>().SingleOrDefault();
var count = product.OrderItems.Count;
Assert.AreEqual(0, statistics.CollectionFetchCount, "Product collectionfetchcount using QueryOver");
}
[Test] /* Fail */
public void Accessing_Collection_Using_Session_Query_Results_In_1_Select()
{
// Get by IQueryable and Linq
var product = Session.Query<Product>().Single(x => x.Id == LastCreated.Id);
var count = product.OrderItems.Count;
Assert.AreEqual(0, statistics.CollectionFetchCount, "Product collectionfetchcount using Linq");
}
[Test] /* Fail */
public void Accessing_Collection_Using_HQL_Results_In_1_Select()
{
// Get by IQueryable and Linq
var product = Session.CreateQuery("from Product where Id = :id")
.SetParameter("id",LastCreated.Id)
.UniqueResult<Product>();
var count = product.OrderItems.Count;
Assert.AreEqual(0, statistics.CollectionFetchCount, "Product collectionfetchcount using HQL");
}
Is this intended behaviour or am I doing something wrong?
HQL queries will not respect a fetch="join" set in mapping. This is because they are freeform queries, making it impossible for NH to guess how to transform them to add the join.
Linq is implemented as a wrapper for HQL, QueryOver is a wrapper for Criteria; that's why you see the different behaviors.
If you need eager loads in Linq/HQL, you will have to make them explicit in the query (using join fetch and Fetch()/FetchMany()

How to manually create Proxy for Detail Collection in NHibernate

I've got class, let it be Foo:
public class Foo
{
...
protected MyCollection<Detail> _details
public virtual MyCollection<Detail> Details
{
get { return _details ?? new MyCollection<Details>(); }
set { _details = value; ... }
}
...
}
public class Detail {...}
When I do LINQ query:
var q = session.Query<Foo>().Select(foo => new Foo( property1 = foo.property1, ... );
...
q.ToList();
I've got NULL in _details field, and when I access to Details to get all Lazy details, of course I get new MyCollection(), but not IPersistentBag (or else, IPersistentCollection).
So How can I manually create proxy collection (I've got session / sessionFactory references)?
[ Added ] here is the mappings (on Foo):
<bag name="Details" lazy="true" collection-type="NHibernateDataService.DetailBag`1[[DataObjects.Detail, DataObjects]], NHibernateDataService" cascade="all-delete-orphan" fetch="select" batch-size="1" access="property" inverse="true">
<key column="`Master`" />
<one-to-many class="DataObjects.Detail" />
</bag>
Thank you!
MyCollection can't be mapped to IPersistentBag, unless, of course, you implement that interface on MyCollection (and probably set the mapping type explicitly??)...
A more standard approach is to set the "collection-type" property on the bag mapping to a custom type - an implementation of IUserCollectionType, which you can choose to make a base class that MyCollection derives from.

How do I sort by a property on a nullable association in Grails?

I'm trying to sort a table of data. I have the following domain (paraphrased and example-ified):
class Car {
Engine engine
static constraints = {
engine nullable: true // poor example, I know
}
}
class Engine {
String name
}
Here's the controller action that's handling the sort:
def myAction = {
def list = Car.findAll(params)
render(view: 'list', model: [list: list])
}
I provision some data such that there are several Cars, some with null engines and others with engines that are not null.
I attempt the following query:
http://www.example.com/myController/myAction?sort=engine.name&order=asc
The results from the query only return Car entries whose engine is not null. This is different from the results that would be returned if I only queried the association (without its property):
http://www.example.com/myController/myAction?sort=engine&order=asc
which would return all of the Car results, grouping the ones with null engines together.
Is there any way that:
I can get the query that sorts by the association property to return the same results as the one that sorts by only the association (with the null associations grouped together)?
I can achieve those results using the built-in sorting passed to list() (i.e. without using a Criteria or HQL query)
You need to specify LEFT_JOIN in the query, try this:
import org.hibernate.criterion.CriteriaSpecification
...
def list = Car.createCriteria().list ([max:params.max?:10, offset: params.offset?:0 ]){
if (params.sort == 'engine.name') {
createAlias("engine","e", CriteriaSpecification.LEFT_JOIN)
order( "e.name",params.order)
} else {
order(params.sort, params.order)
}
}
Remember to put engine.name as the property to order by in your list.gsp
<g:sortableColumn property="engine.name" title="Engine Name" />

A better solution than element.Elements("Whatever").First()?

I have an XML file like this:
<SiteConfig>
<Sites>
<Site Identifier="a" />
<Site Identifier="b" />
<Site Identifier="c" />
</Sites>
</SiteConfig>
The file is user-editable, so I want to provide reasonable error message in case I can't properly parse it. I could probably write a .xsd for it, but that seems kind of overkill for a simple file.
So anyway, when querying for the list of <Site> nodes, there's a couple of ways I could do it:
var doc = XDocument.Load(...);
var siteNodes = from siteNode in
doc.Element("SiteConfig").Element("Sites").Elements("Site")
select siteNode;
But the problem with this is that if the user has not included the <SiteUrls> node (say) it'll just throw a NullReferenceException which doesn't really say much to the user about what actually went wrong.
Another possibility is just to use Elements() everywhere instead of Element(), but that doesn't always work out when coupled with calls to Attribute(), for example, in the following situation:
var siteNodes = from siteNode in
doc.Elements("SiteConfig")
.Elements("Sites")
.Elements("Site")
where siteNode.Attribute("Identifier").Value == "a"
select siteNode;
(That is, there's no equivalent to Attributes("xxx").Value)
Is there something built-in to the framework to handle this situation a little better? What I would prefer is a version of Element() (and of Attribute() while we're at it) that throws a descriptive exception (e.g. "Looking for element <xyz> under <abc> but no such element was found") instead of returning null.
I could write my own version of Element() and Attribute() but it just seems to me like this is such a common scenario that I must be missing something...
You could implement your desired functionality as an extension method:
public static class XElementExtension
{
public static XElement ElementOrThrow(this XElement container, XName name)
{
XElement result = container.Element(name);
if (result == null)
{
throw new InvalidDataException(string.Format(
"{0} does not contain an element {1}",
container.Name,
name));
}
return result;
}
}
You would need something similar for XDocument. Then use it like this:
var siteNodes = from siteNode in
doc.ElementOrThrow("SiteConfig")
.ElementOrThrow("SiteUrls")
.Elements("Sites")
select siteNode;
Then you will get an exception like this:
SiteConfig does not contain an element SiteUrls
You could use XPathSelectElements
using System;
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;
class Program
{
static void Main()
{
var ids = from site in XDocument.Load("test.xml")
.XPathSelectElements("//SiteConfig/Sites/Site")
let id = site.Attribute("Identifier")
where id != null
select id;
foreach (var item in ids)
{
Console.WriteLine(item.Value);
}
}
}
Another thing that comes to mind is to define an XSD schema and validate your XML file against this schema. This will generate meaningful error messages and if the file is valid you can parse it without problems.

Resources