4

Inside the CP, is it possible to pull the ID for the current field layout being rendered (both in the Field Layout Designer and in element editing forms)?

A bit of context:

I'm writing a plugin which adds functionality to the built-in Field Layout Designer. The extra functionality basically allow admins to add metadata when they are editing field layouts. This metadata is stored in a custom table, using the field layout's ID as FK. The idea is that whenever a field layout is rendered (either inside the FLD, or when an element is edited/created) the plugin should pull the metadata for the current field layout.

Modifying the FLD UI is easy – when the plugin loads, I basically check the DOM (with jQuery) for a FLD container. If a container is found, the plugin loads up a script.

Saving the metadata is also easy; the plugin hooks into fields.saveFieldLayout like this:

craft()->on('fields.saveFieldLayout', function (Event $e) {
    $myPluginModel = new MyPlugin_MyPluginModel();
    $myPluginModel->fieldLayoutId = $e->params['fieldLayout']->id;
    $myPluginModel->metadata = craft()->request->getPost('myPlugin.metadata');
    craft()->myPlugin->saveStuff($myPluginModel);
});

The hard part is querying for the relevant metadata whenever a field layout is rendered, because I can't find a way to pull the currently rendered field layout's ID.

Here's ideas I've explored/solutions that doesn't work:

  1. Neither the FLD nor the element editing forms expose their field layout's ID to the the DOM.

  2. I've looked at the HttpRequestService to see if the field layout ID (or any other data I could use to query for the field layout ID) could be pulled from the request.

  3. I've tried accessing the current controller class via craft()->controller – thinking if I could get to the current element type I might be able to pull the field layout from its model, but craft()->controller is always NULL.

  4. I've attempted to pull the global Twig context (via craft()->templates->twig) to look for the fieldLayout variable.

  5. Ideally, I wouldn't want to pull the relevant metadata client side (i.e. with AJAX), but I did also look at the global Craft JS object to look for clues, but found nothing.

  6. Parsing the request path and storing the ID of the entry type, asset source, category group etc. along with the field layout ID would work. I'd like to avoid this, because it makes it impossible to support custom element types without hard coding stuff.

If it isn't possible – by any means – to pull the current field layout ID, the alternative approach is to somehow figure out which element type is being edited, then pull that element type's model and finally get the field layout model/ID from there. Ideally, I'd like to do this without having to hard code attribute names (i.e. entryTypeId, categoryGroupId etc), because I want this to work for any custom element type, too. Any suggestions in this regard is very welcome, as well.

1 Answer 1

3

It looks like EntryTypeModels have a fieldLayoutId attribute. By inspecting the route params, we can get the entry type ID, and then create a model from that. Other than this, I haven't been able to find anything passed to the FLD.

    $params = craft()->urlManager->getRouteParams();
    $variables = $params['variables'];
    $matches = $variables['matches'];
    $entryTypeId = $matches['entryTypeId'];
    $entryType = EntryTypeRecord::model()->findById($entryTypeId);
    $fieldLayoutId = $entryType->fieldLayoutId;

Hopefully this helps!

Edit:

I also found that a fieldLayoutModel is passed to the fieldlayoutdesigner.html template when it is included. See the include in templates/settings/section/_entrytypes/edit.html as an example. Content from the FieldLayoutModel is then loaded.

I know you said you would rather not load with ajax, but it is definitely better than nothing. I don't see any hook or event that gives you access to this information.

You could do something like

var fieldLayoutId = '{{ fieldLayout.id|e('js') }}';

from within your included js file and then go pull your metadata via ajax.

6
  • I think this is my best option so far. A couple of issues though – first, testing for route params on BasePlugin::init is too soon. I need to get to check for the fieldLayoutId on basically every GET request/standard pageload, not only on fields.saveFieldLayout. The only event I've found to listen to is elements.populateElement, although that fires once for every element on the page :/ The bigger problem is that just like with request path parsing, this would require me to hard code which attributes to look at (e.g. entryTypeId), making it difficult to support custom element types. Commented Nov 10, 2015 at 8:29
  • Where did you add the above code? Inside an event listener? Which event did you listen for? Commented Nov 10, 2015 at 8:29
  • 1
    I just threw this in a variable method and called it right from the FLD template to see if there was anything of use, since route parameters would always resolved at that point. Unfortunately I haven't gone any more in depth.
    – kcolls
    Commented Nov 10, 2015 at 15:29
  • I added an edit finding a little more information that I found. I still can't find an elegant solution.
    – kcolls
    Commented Nov 11, 2015 at 22:49
  • Thanks a lot for continuing to poke at this – I really appreciate it! Actually, your latest edit is really interesting. If I can somehow dump the fieldLayout variable from `fieldlayoutdesigner.html – JS or not – it's on :) I'm going to try out a couple of ideas. Thanks again! Commented Nov 11, 2015 at 23:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.