- Modeling
- Entities
Projections
To populate a user interface, a specification will need to add details to its results.
To accomplish this, create an object in the select clause.
The object can include properties that are computed from child specifications.
For the blog application, we'll want to display a list of sites.
The user will need to see the name of each site in the list.
Let's modify the sitesByUser specification to include the names of each site.
var sitesByUser = Given<User>.Match((user, facts) =>
from site in facts.OfType<Site>()
where site.creator == user
where !facts.Any<SiteDeleted>(
sd => sd.site == site &&
!facts.Any<SiteRestored>(sr => sr.deleted == sd))
select new
{
Site = site,
Names =
from name in facts.OfType<SiteName>()
where name.site == site
where !facts.Any<SiteName>(next => next.prior.Contains(name))
select name.value
});
var sites = await jinagaClient.Query(sitesByUser, user);
sites
| index | value |
|---|
| 0 | { Site = Site { creator = Jinaga.User, createdAt = 5/18/2024 5:54:05 PM }, Names = System.Linq.Enumerable+<OfTypeIterator>d__66`1[System.String] }
|
| Site | Site { creator = Jinaga.User, createdAt = 5/18/2024 5:54:05 PM }
|
| creator | Jinaga.User
| | createdAt | 2024-05-18 17:54:05Z |
| | Names | [ My Journal ]
|
|
With this structure, the user interface can generate a list of sites.
The Names property is going to be a collection of names, not a single value.
The user interface might use FirstOrDefault to turn it into a single value.
var sitesViewModel = sites.Select(s => new
{
Name = s.Names.FirstOrDefault() ?? "New site"
});
sitesViewModel
| index | value |
|---|
| 0 | { Name = My Journal }
|
Continue With
Additional Mutable Properties