2

Is it possible to do the following in Craft?

I want to set up course information as follows:

1) have a courseType which contains default values for that type of course - name (i.e. 3 hour skills, full day masterclass etc), price, capacity, trainers etc

2) have a course which has a courseType entry filed among other details such as details of the course, equipment used, etc. The course will also have fields for price, trainers & capacity.

Is it possible to have the course price, trainers & capacity fields filled with the value of the courseType selected when it is chosen in the CP new course page? These course fields should then be able to be overridden if required on a course by course basis.

Any suggestions would be very welcome - I'm new to craft and can find any examples like this.

Thanks in advance.

| improve this question | | | | |
  • When it's only about the CP you can go into an entry and use the save as new entry function. Otherwise it requires a plugin to use certain hooks to overwrite the default values. Is this function mainly for the CP or do you want to be able to show "fallback" values in your frontend as well? – Robin Schambach Feb 28 '18 at 16:03
  • Thanks Robin - It would be CP only. There will be a few course types with several default values as described, the goal it to allow the creation of courses that will 'inherit' these default values when the course type is chosen. It is to speed up course creation for the client as there will be many similar ones created on an ongoing basis. – Sjc Feb 28 '18 at 16:10
  • Then you have to decide the way you want to go... the "easy" way would be to create "template" courses and set their status as deactivated so they won't appear in your frontend and tell your customers to use those template entries to create new entries. The other way would be to use the cp.entries.edit' hook to insert your values. I can show you how if you want, just let me know – Robin Schambach Feb 28 '18 at 16:14
  • I would rather go the more involved way if it meant that the client can add new course types without having to have the corresponding course template made. So would I have to implement the functionality as a plugin/module that monitored change events on this specific kind of field and then dynamically update related fields in the course entry page data? If so where would I find documentation on the undocumented cp.entries.edit :-) Thanks for the information so far. – Sjc Feb 28 '18 at 17:25
1

First of all I would like to leave a few links for you.

  1. Pluginfactory.io is a page where you can create your "starting" files. It creates an empty Plugin, with all the required files/functions with example codes for routing and services....
  2. The Docs about Craft Plugin developement

Then to the code: you'll need to insert a function like this in your Plugin's primary class

craft()->templates->hook('cp.entries.edit', function(&$context) {
    if ($context['sectionHandle'] === 'course') {
        // you can get these from a config file or you could create
        // plugin settings, I'll just insert an array here, it's faster
        $config = [
            'entryTypeOne'     => [
                'title'         => 'A title',
                'body'          => 'some information',
                'relationField' => [1, 2, 4] //<-- array of element ids
            ],
            'anotherEntryType' => [
                'title'         => 'Another title',
                'body'          => 'some more information',
                'relationField' => [] //<-- array of element ids
            ]
        ];

        /** @var \Craft\EntryModel $entry */
        $entry = $context['entry'];
        $entry->getContent()->setAttributes($config[$entry->getType()->handle]);
    }
}

However: unfortunately you can't set default values when the user changes the entry type with this method, thus we'll need another "hack". As you can see in the Relabel Plugin Craft provides ways to change default functions. You can insert this javascript

Craft.EntryTypeSwitcher.prototype.onTypeChange =  function(ev)
{
    this.$spinner.removeClass('hidden');

    Craft.postActionRequest('entries/switchEntryType', Craft.cp.$container.serialize(), $.proxy(function(response, textStatus) {
        this.$spinner.addClass('hidden');

        if (textStatus == 'success')
        {
            var fieldsPane = this.$fields.data('pane');
            fieldsPane.deselectTab();
            this.$fields.html(response.paneHtml);
            fieldsPane.destroy();
            this.$fields.pane();
            Craft.initUiElements(this.$fields);

            Craft.appendHeadHtml(response.headHtml);
            Craft.appendFootHtml(response.footHtml);

            // Update the slug generator with the new title input
            if (typeof slugGenerator != "undefined")
            {
                slugGenerator.setNewSource('#title');
            }
        }
    }, this));
}

To change the default behavior when someone changes the entry type. All you have to do is to change the destination of the script from

Craft.postActionRequest('entries/switchEntryType'

to something like

Craft.postActionRequest('yourpluginhandle/controllername/switchEntryType'

Then you'll take the default EntriesController function

public function actionSwitchEntryType()
{
    $this->requirePostRequest();
    $this->requireAjaxRequest();

    $entry = $this->_getEntryModel();
    $this->enforceEditEntryPermissions($entry);
    $this->_populateEntryModel($entry);

    $variables['sectionId'] = $entry->sectionId;
    $variables['entry'] = $entry;
    $variables['showEntryTypes'] = true;

    $this->_prepEditEntryVariables($variables);

    $paneHtml = craft()->templates->render('_includes/tabs', $variables) .
        craft()->templates->render('entries/_fields', $variables);

    $this->returnJson(array(
        'paneHtml' => $paneHtml,
        'headHtml' => craft()->templates->getHeadHtml(),
        'footHtml' => craft()->templates->getFootHtml(),
    ));
}

And do exactly the same like in the first function

$entry->getContent()->setAttributes($config[$entry->getType()->handle]);

Unfortunately if you want to take care of all use cases you have to overwrite another function. When someone is trying to create an entry via an ElementEditor(the thing that pops up when you click on "new entry") in a relation field. It works exactly the same like my first method and it's the same like Here

| improve this answer | | | | |
  • Thanks Robin, thats a huge help - lots of information to get started with. – Sjc Mar 1 '18 at 8:45
  • Let me know if you need any help. It's relative easy but it can be hard to get into it the first time. I can also provide help in chat after you reached a certain level here – Robin Schambach Mar 1 '18 at 8:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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