Skip to content

SearchKit - Allow subsearch of different types - #34853

Merged
mattwire merged 4 commits into
civicrm:masterfrom
colemanw:subsearchTypes
Mar 2, 2026
Merged

SearchKit - Allow subsearch of different types#34853
mattwire merged 4 commits into
civicrm:masterfrom
colemanw:subsearchTypes

Conversation

@colemanw

@colemanw colemanw commented Feb 20, 2026

Copy link
Copy Markdown
Member

Overview

Enables Subsearches on any search display of any other type of search display.

Technical Details

I gave up on lazy-loading search display modules. So this adds a new crm-search-display wrapper directive which pre-loads all viewable search displays as dependencies.

@civibot

civibot Bot commented Feb 20, 2026

Copy link
Copy Markdown

🤖 Thank you for contributing to CiviCRM! ❤️ We will need to test and review this PR. 👷

Introduction for new contributors...
  • If this is your first PR, an admin will greenlight automated testing with the command ok to test or add to whitelist.
  • A series of tests will automatically run. You can see the results at the bottom of this page (if there are any problems, it will include a link to see what went wrong).
  • A demo site will be built where anyone can try out a version of CiviCRM that includes your changes.
  • If this process needs to be repeated, an admin will issue the command test this please to rerun tests and build a new demo site.
  • Before this PR can be merged, it needs to be reviewed. Please keep in mind that reviewers are volunteers, and their response time can vary from a few hours to a few weeks depending on their availability and their knowledge of this particular part of CiviCRM.
  • A great way to speed up this process is to "trade reviews" with someone - find an open PR that you feel able to review, and leave a comment like "I'm reviewing this now, could you please review mine?" (include a link to yours). You don't have to wait for a response to get started (and you don't have to stop at one!) the more you review, the faster this process goes for everyone 😄
  • To ensure that you are credited properly in the final release notes, please add yourself to contributor-key.yml
  • For more information about contributing, see CONTRIBUTING.md.
Quick links for reviewers...

➡️ Online demo of this PR 🔗

@civibot civibot Bot added the master label Feb 20, 2026
Directive can load any viewable search.
Uses the new crm-search-display directive to enable non-table subsearches.
No need for dynamically generated templates when we can just use the one generic `crm-search-display` element.

Just requiring crmSearchDisplay, the dependencies sort themselves out and we don't need to declare `basePages` for every display.
Comment on lines +7 to +11
type: '@',
apiEntity: '@',
search: '<',
display: '<',
settings: '<',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@colemanw could we remove type and settings here and fetch them in the component based on search and display?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yea they're probably usually contained within those arrays.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ufundo actually no, they're not. search and display are strings not arrays. The only array passed in is the settings. So all this stuff needs to be passed thru.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So my thinking is they are logically dependent, rather than literally one includes the other.

My first though was something like:

this.$onInit = () => {
   this.display = crmApi4('SearchDisplay', 'get', {
     select: ['type', 'settings'],
     where: [['name', '=', this.display], ['saved_search_id.name', '=', this.search]]
   })[0];
   ...

It's an extra api request, and it wont work well in the editor, but it is much more convenient if you are writing html/smarty templates to not have to fetch those things in advance.

Maybe it could be a fallback/lazy option:

this.$onInit = () => {
   if (!this.type || !this.settings) {
     const savedDisplay = crmApi4('SearchDisplay', 'get', {
       select: ['type', 'settings'],
       where: [['name', '=', this.display], ['saved_search_id.name', '=', this.search]]
     })[0];
     this.type = this.type ? this.type : savedDisplay['type'];
     this.settings = this.settings ? this.settings : savedDisplay['type'];
     ...

That would be more of a follow-up than a blocker.

@colemanw colemanw Feb 23, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ufundo it sounds like a good idea, but I think there's 2 potential problems:

  1. In a Subsearch scenario, with 50 rows per page (default) that's 50 extra ajax requests per subsearch!
  2. Users might not be allowed to call the 'SearchDisplay', 'get' ajax api depending on their permission levels.

If we really wanted to solve both problems, the metadata about the search display could be returned as part of the first searchDisplay.run request as an extra SearchDisplayRunResult property... In theory, I haven't tried it, you could fetch metadata about the search AND run the search in the same ajax request.
But that's a potentially YAGNI project and we've got bigger priorities IMO.

The real downside to this PR is that it loads ALL searchDisplay code ALL the time (e.g. all of ChartKit, etc). But js is browser-cacheable so probably not worth wringing our hands about.

@cs-bennwas

Copy link
Copy Markdown

I tried subsearches with list displays and it works well. It's a big improvement UI and performance wise if all you care about is a simple summary. Which our clients want quite often.

@colemanw colemanw added the merge ready PR will be merged after a few days if there are no objections label Feb 28, 2026
@mattwire
mattwire merged commit 78549ad into civicrm:master Mar 2, 2026
1 check passed
@colemanw
colemanw deleted the subsearchTypes branch March 2, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

master merge ready PR will be merged after a few days if there are no objections

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants