Updating a plugin from Craft 2 to Craft 3, so this logic used to work.

The plugin has a field-type which is a button. When clicked, the button does stuff depending upon another field. That handle(ID) of that other field must be passed to the button's javascript.

The field's class seems to register the js correctly. When the page loads, it gives a popup with the correct info.

var startDateFieldHandle = 'fields-startDate';
alert( 'startDateFieldHandle = '+startDateFieldHandle);

Above that is <script src="http://f.dev/cpresources/6991e452/occurrencesField.js?v=1527142206"></script> which pulls in the following:

    $("#fields-cal37_choose_dates_button").click( function() { 
        alert('Clicked the button');
        var start_date = new Date( jQuery("#"+startDateFieldHandle).val() );

The alerts happen in the correct sequence, but nevertheless my guess is that because <script cpresources> bit occurs earlier on the page than where startDateFieldHandle is set, that somehow it still isn't set when the button is clicked.

I don't see, using Craft::$app->View->registerJs($js); that there is any way to say "put this first."

It did used to work under Craft 2. Any tips?

At present, I'm seeing in occurrencesField.js that as soon as I reference the startDateFieldHandle variable in any way, such as alert(startDateFieldHandle); the script quits.

Also, in the Firefox console, I'm getting:

jQuery.Deferred exception: startDateFieldHandle is not defined @http://f.test/cpresources/6d6f7137/occurrencesField.js?v=1527518592:101:2
 undefined  jquery.js:1:31365
Double-instantiating a menu button on an element garnish.js:1:2512

1 Answer 1


Keep in mind Craft parses the html of your field, it won't be used directly, thus the ID of your field can't be "#"+startDateFieldHandleunless you ignored Crafts methods or modified it in another way. Your fields ID will be more like

id="fields-{{the id you specified}}"

Thus you should make sure you used the correct selector like


usually your order should be fine.. If you want to pass certain variables to Javascript you should do that in Twig because Craft::$app->View->registerJs($js); won't pass variables in a global scope (you can't access them in your JS files in certain cases).

However you should avoid using those globals in Craft. It's better to create a custom Garnish object for the logic

Craft::$app->getView()->registerJs('new Garnish.MyAwesomeField(id, options)');

That will make sure everything is initialized and ready to use Your js could look like this

Garnish.MyAwesomeField = Garnish.Base.extend(
        $theOtherField: null,
        $field: null,
        options: {},
        init: function (fieldId, settings) {
            this.options = $.extend({}, Garnish.MyAwesomeField.defaults, settings);
            this.$theOtherField = $('#' + this.options.fieldSelector + this.options.theOtherFieldHandle);
            this.$field = $('#' + this.options.fieldSelector + fieldId);
            this.addListener(this.$field, 'click', $.proxy(this, 'clickEvent'));
        clickEvent: function(){
            alert( this.$theOtherField.val() );

            fieldSelector: 'fields-',
            otherFieldHandle: ''
  • Sorry, I got pulled away a few days. Thank you so much, Robin, for the time and care you put into answering this question. I really appreciate it!
    – kr37
    Commented May 28, 2018 at 13:04
  • I'm trying to wrap my head around this Garnish object. My custom "field" is a button that posts to a controller which sends back some mini-ajax-calendars for inserting and deleting events from the calendar.
    – kr37
    Commented May 28, 2018 at 14:54
  • So this garnish object gives a place to keep some information, and it should be updated correctly, and it also can provide a listener for the the click event? And in the php preceding this, I set $theOtherField = 'startDateField'
    – kr37
    Commented May 28, 2018 at 15:03
  • "o this garnish object gives a place to keep some information, and it should be updated correctly, and it also can provide a listener for the the click event?" -> yes.... You can insert all needed options via PHP and pass it to the object like in my example. options will be an array of your settings like the other field handle or whatever you need Commented May 28, 2018 at 15:23
  • In your garnish.js, you use this.$field. Why not hardcode this as this.fieldId ?
    – kr37
    Commented May 28, 2018 at 15:50

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.