Embed Express Form block inside Express Entry List Block, plus modify form field and insert data

I have a template that I’ve been building for an Express_Entry_List block. It pulls data from an Express Object and it’s Entries, plus associated Express Entries from other Express Objects. For the sake of explanation, the Express Entry List lists Tournaments for an event, and the associated Express Objects include which Game the Tournament is for, so we can show the Name of the Game, the Game’s graphical banner, and stuff like that. I have that working rather well, looks pretty tasty, and I’m using the magnific-popup css/js package for tasty pop-ups (although I still need to clean up the code and not do in-line, but I digress).

Anyways…

Part of outstanding (as in, incomplete) functionality that I need to figure out, is participant registration for each tournament, and that needs to be possible in 3x different ways, as an individual, creating/joining a team, and creatining/joining a roster for more permanent teams (another term is used that I won’t go into here).

Now, I’m pretty sure I can bang out a solution for joining as an individual, just a link that programmatically creates an Express Entry based on the logged in user, which Express Entry the List block is rendering, and stuff like that.

The part that I am trying to figure out, and documentation is falling short on me, is the Team Create/Join aspects… specifically Create (as I have an idea on the Join aspect).

What I’m hoping to do is have each Express Entry in the List block (each Tournament is displayed separately from the next as each is a different Entry), have a link the user clicks/taps on, it pops-up (magnific-popup) and in there is a short form, “Team Name” and a “submit” equivalent button. Standard stuff I’m sure (although embedding one block in another I am still not sure how much I need to achieve that).

However, what I want is that Form to have a field that is hidden to the user, which gets pre-filled by which Tournament the Form is for (based on which Entry the user clicked/tapped on).

I found this method to partly get me the way there… : html - PHP TextBox Value Before Submission - Stack Overflow

Whereby I stuff the Tournament Express Entry into a variable $whichTournament (or whatever, the name doesn’t matter) and modify the value of that field in the form in similar vein as…

value="<?php echo $whichTournament->getAttribute('attribute_handle'); ?>"

Naturally customising it to the actual value I want, I’m just showing for historic/explanation purposes.

The issue I’m having is I really don’t know how to declare which field in the form to apply this to, and I also need to modify that same field probably to:

type="hidden"

I also want to apply themeing/styling to it, but I suspect that is likely handled by the template that is already defining/rendering the “parent” Express Entry List block.

So… I hope this makes sense, but can I get some help with some explicit code examples that I can modify to make this work? I’m trying to build a really good User eXperience here, and this last bit I can’t wrap my head around (modifying just the one Form field, and how to declare it, etc).

Thanks!

The area I’m really most stuck in here is making a specific form field hidden and automatically populated with a value (pulled from an express entry). If someone could help outline how to do that I think I may be able to figure out the other parts.

Any chance someone can help? Please?

How do you actually render form in popup? It’s not clear. Is it hand-written html code/Form block is being used for that/something else?

The ask is more about the form aspect, hiding the field and pre-populating it with a value (selecting which Express Entry through an Association in this specific case).

As for the pop-up, using jquery magnific popup.

I am not yet actually rendering the form in any way, as I am trying to get help with the method before I start writing the code for the form aspect being embedded in the parent block. So I don’t have code specific to the form to show.

How do I go about hiding the field and pre-populating it with an Express Entry selection through an Association?

So yeah, you can hide field as <input type="hidden"> or just styling it as display: none; in css.

Magnific popup can open popup in “inline” mode, so you can just “duplicate” form for every tournament (each target div should have different id) in php foreach loop.
If you want to use only one form, you have to use javascript to change input value on popup open action (for example, you store id as data attribute and then you copy value in js to your hidden field).

Though your question is so general, I am still not sure what “tech” you want to use in the end (do you want to use only built-in express blocks/code form manually/generate form automatically from Express etc.). This can be done in multiple ways, so you have to be more specific not only about details but general info too.

Your first post is so long but taps into so many things, I am having hard time to infer what the problem actually is. Do you have problems with Concrete or is it general coding question?

  1. When I look at the extended (contexts, etc) documentation on customising forms, I don’t see a way to specifically target one specific form field for modification (which is where my head is at), so I wasn’t sure if contexts were where I should go, or just templating. Namely since I am unsure how to apply a theme template to a block embedded in a block (Express Form Block embedded in Express Entry List Block).
  2. You’re on the same wavelength regarding each div having their own id and data, that’s generally what I was planning around.
  3. The method I was anticipating I could use is this one ( html - PHP TextBox Value Before Submission - Stack Overflow ) whereby I pipe data into a specific field (referenced example below 1). However the area I am getting tripped up on is I am unsure how to apply that to a specific form field in the manner I am describing.
  4. I don’t mind handling this with CSS, or modifying the <input…> HTML declaration, I just again am unsure what (simple?) method I can use to target a specific Express Form field with how the $render function looks to operate.
  5. I don’t want to write blocks from scratch, my intent is to take the existing blocks and template (and/or context modify?) them to meet my needs. So in this case the parent block is Express Entry List Block, and the “embedded” is Express Form Block (so to say, or just an Express Form, if there’s any actual difference there).
  6. The problem doesn’t look to be specifically with Concrete, more just I haven’t been able to find any examples/resources on modifying specific Express Form Fields in this way (hide a specific field for a form, and in that same specific field pre-fill data before user hit’s “submit”)

I really am trying to be clear here, so I’m sorry for confusion regarding my explanations here.

Example 1:

value="<?php echo $ui->getAttribute('attribute_handle'); ?>"

By default, generated fields in Form block don’t have anything “unique” that you can use for targeting.
So for example, text fields looks like that:

<div class="mb-3">
    <label class="form-label" for="akID[37][value]">Example label</label>
    <input type="text" id="akID[37][value]" name="akID[37][value]" value="" placeholder="" class="form-control ccm-input-text">
</div>

And you probably would like to change it to something like that:

<div class="mb-3" data-field-handle="express_field_handle">
    <label class="form-label" for="akID[37][value]">Example label</label>
    <input type="text" id="akID[37][value]" name="akID[37][value]" value="" placeholder="" class="form-control ccm-input-text my_own_custom_class">
</div>

So you want to add custom data attrs, classes on inputs/wrappers etc. generated by Form block.
Am I correct?

I conceptually “know” what I want, as for the technical method, I’m intentionally leaving that open. As for adding/replacing classes on a form field, adding custom data attributes, sure.

But when I read through the documentation that seems to be relevant (but I am unsure if the context method is overkill vs just templating or not), I don’t see how in the context (or other aspects of the documentation describing the more advanced way to modify the Express Forms) I can add classes, or other html aspects to (a) specific form field(s).

As in, the base block template is the $render function (I don’t have the exact syntax in front of me), and then that results in generating the HTML and other aspects that ends up being the relevant Express Form itself, but modifying that rendering… for a specific form in my specific scenario, I’m not seeing how to modify that so I can then modify the specific HTML tags and related aspects.

Documentation I’m referring to : Using Contexts to Customize Form and Attribute Markup :: Concrete CMS

So… I don’t know if it’s easier, or “harder” (more complex) than I think it may be in my head, as I’m not yet connecting the dots.

Are you stuck at something specific down the line or do you have problems even to start modifying anything (talking about Express Form guides)? Express form modification is kinda over-engineered and definitely has a steep learning curve.

Yes, you have to override core attribute field (relationship field in your case) and probably replace it with hidden input (with data-field-handle=“field” attribute for passing data) for that specific block template.
1 Express List block and 1 Express Form block added on page would be sufficient for that, I guess.

Alternative way is to use just “Express List block” and code your own form/controller for handling validation/data saving (you can still use Express database). It would probably be the same or less amount of work compared to tinkering with express form block (depending on your experience).

  1. Thus-far the majority of what I’ve done with Express Forms to date has been CSS themeing (via template mechanism) to resize input fields (text, checkbox, whatever) and that’s gone well, but I don’t think that’s “enough” for this case.
  2. I’m really mostly looking for some specific details to help me connect the dots, tell me “yes or no you do/n’t need contexts” and some example code specific for modifying the form in-whole, to piece the puzzle together.
  3. I’d prefer to re-use the Express Form stuff so I don’t rewrite the universe just to make a pie.

Thoughts?

Sure, I can prepare/show some code. Though confirm, that this is more or less what you are doing:

You will have two Express objects (with example handles and fields) set up in dashboard:
a) submission (relationship with tournament - you can select only one tournament, email etc.) ← this is where you will be storing submissions from Form block.
b) tournament (id, name, reverse relationship with submission)
Rest is probably irrelevant right now.

You’re not quite yet on the same wavelength.

So, there’s an Express Object “Tournaments”, and an Express Object “Tournament Registration” (for the sake of simplicity).

The “Tournaments” Entries, each represent a Tournament, and they have their own set of data, rules, game select, tied event, etc whatever.

The “Tournament Registration” Entries, each represent a user that has registered for a tournament. So which tournament (and implicitly/relationally which event) they “selected” and which user did so at the time (plus a few other irrelevant things I forget).

===

I already have a theme for the Express Entry List Block that shows Tournaments. And each Tournament in the “list” is customised to make it look nice and all that.

Within this Express Entry List Block (that shows tournament), in each of the “iterations” for each tournament (as in, within the area that shows each tournament), I want to pop-up (ignore this part, except just for explanation) a display which “shows” the form for registering for that tournament.

But, in reality, I want that pop-up to just have a “Register” button, and the “Which Tournament” (or equivalent) field to be hidden and pre-populated with which tournament was selected, based on which link was clicked on for which tournament, in the Express Entry List Block.

===

I am not trying to describe where a user selects manually which tournament from a list (I already went down that rabbit hole, and filtering out irrelevant tournaments is looking to be more work than this method).

===

Hope that clears that up! :slight_smile:

We are exactly on the same wave length. I just described the same thing, only from the point of how it is structured in backend. Which is important thing to know, before start coding anything.

Anyway I will throw some code here later, cheers.

Oh, sorry, lol, thought you were describing it from a User eXperience perspective :stuck_out_tongue_winking_eye:

Thanks for your time and help! \o/

For start, I suggest making these overrides in package.
Depending what do you want to modify, you will need to create files in different folders - it could be hard to keep up where related files are located otherwise.

I have uploaded example package with overrides to GitHub.

I will use that repository in future and populate it with different/more examples, but you can download it now as it is.

A few pointers:

  1. packages/tournament_registration_form/controller.php
    Most important things are:
  • $pkgAutoloaderRegistries which sets namespace to all files in src folder
  • on_start() method where you will state which Express object you want to modify and and which controller to use for that.
  1. packages/tournament_registration_form/src/Express/Controller/TournamentRegistrationFormController.php
    This just registers context. You can also add custom validation here but I haven’t done it in this package.

  2. packages/tournament_registration_form/src/Express/Form/Context/TournamentRegistrationFormContext.php

  • setLocation() is used for overriding custom Express control types (text label, association, form)
  • getAttributeContext() will forward you to another class
  1. packages/tournament_registration_form/src/Attribute/Context/TournamentRegistrationFormContext.php
  • method in construct is used for overriding attributes (text, textarea, number, date_time etc.)
  • setLocation() is used for overriding the HTML surrounding an attribute
  1. You can find all overridden view files in this package (that’s why I suggested making it a package).
    I left notes in comments where you can find original files.

  2. packages/tournament_registration_form/blocks/express_entry_list/templates/tournament_registration_form/view.php
    Block template is also put here, because why not.

  3. In package, you will find that I have added express key handles, which are unique for form + some other stuff.
    For example, I have added data-express-field-handle="tournament" in:
    public/packages/tournament_registration_form/elements/express/form/tournament_registration_form/association/select.php:46

You can also add style="display: none;" on select (or wrapper in different override) to hide it.

General idea is that:

  • One “Express list” block + one “Express form” is added on your page.
  • Popup will open on Tournament link click.
  • You should add something like: data-id="<?= h($item->getEntry()->getId()); ?>" to Tournament link in “Express list” block.
    And use it in your javascript code when clicking link. You know id of Tournament → you can set programmatically value of association in your popup “Express form”.

I need to review what you have here further, but just a quick note, as I’m not sure if it’s relevant, my current usecase is Concrete 8.5+, as I’m not yet at 9.x. So if there’s anything I need to change based on that, please let me know. :slight_smile:

But I need to read through your response here fully, thanks! :smiley:

I haven’t tested it on 8, but there shouldn’t be massive changes, if any. Set PHP to 7.4 though.

@Parasek I’m reading through the various files in this repo (thanks by the way!), and it’s not really jumping out at me as to which of these I would want to modify (in theory) to declare which Form field I want to “make hidden” and “insert value” into. While you’ve clearly put a substantial amount of work into this (again, thanks!), I’m not exactly seeing an example override with the make hidden + insert value (although I may just not be looking at the right part).

Can you clarify, or perhaps update it a touch to include this (maybe missing?) example customisation please?

Example association selector field is included in repo:

https://github.com/parasek/concretecms-express-form/blob/master/elements/express/form/tournament_registration_form/association/select.php

targetHandle is variable that stores current express field handle.

line 21: $targetHandle = $association->getTargetEntity()->getHandle();

You can move it to the top of code and then add class/styling to wrapper div, like:

<?php defined('C5_EXECUTE') or die('Access Denied.'); 

$targetHandle = $association->getTargetEntity()->getHandle();
?>

<div class="mb-3" <?php if ($targetHandle  === 'your_attribute_field_handle_from_express'): ?>style="display: none"<?php endif; ?>>
?>

Of course you can use data- attribute and control it using javascript (instead php like here). Just add

<div class="mb-3" data-express-field-handle="<?= h($targetHandle); ?>">

and you can select it using jquery or querySelector().

Association selector is kind of “special” field. Rest of attributes reside in attribute folder. You need to browser concrete source code (I left notes), to find original files before copying them.

And also:
a) you need to override every field type separately (unless you are modifying bootstrap5 wrapper for attributes).
b) this package modifies only frontend form display that is based on “tournament_registration” Express object only.
c) it is the whole point to add data-express-field-handle="tournament" to every “association field”. It doesn’t collide with anything and you can safely control it with javascript. Those data attributes in 99% situations will be unique (you will most likely not add the same express form on one page).