Answers.Body: <p>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 <code>"#"+startDateFieldHandle</code>unless you ignored Crafts methods or modified it in another way. Your fields ID will be more like</p>
  
  <pre><code>id="fields-{{the id you specified}}"
  </code></pre>
  
  <p>Thus you should make sure you used the correct selector like</p>
  
  <pre><code>jQuery("#fields-"+startDateFieldHandle)
  </code></pre>
  
  <p>usually your order should be fine.. If you want to pass certain variables to Javascript you should do that in Twig because <code>Craft::$app-&gt;View-&gt;registerJs($js);</code> won't pass variables in a global scope (you can't access them in your JS files in certain cases).</p>
  
  <p>However you should avoid using those globals in Craft. It's better to create a custom <code>Garnish</code> object for the logic</p>
  
  <pre><code>Craft::$app-&gt;getView()-&gt;registerJs('new Garnish.MyAwesomeField(id, options)');
  </code></pre>
  
  <p>That will make sure everything is initialized and ready to use
  Your js could look like this</p>
  
  <pre><code>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() );
  
          }
      },
      {
          defaults:{
              fieldSelector: 'fields-',
              otherFieldHandle: ''
          }
      }
  );
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-28T13:04:27.423Z
Answers.Text: 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!
Answers.UserDisplayName: kr37
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-28T14:54:03.403Z
Answers.Text: 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.
Answers.UserDisplayName: kr37
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-28T15:03:09.330Z
Answers.Text: 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'`
Answers.UserDisplayName: kr37
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-28T15:23:53.317Z
Answers.Text: "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
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-28T15:50:57.663Z
Answers.Text: In your garnish.js, you use `this.$field`. Why not hardcode this as `this.fieldId` ?
Answers.UserDisplayName: kr37
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-28T20:03:35.383Z
Answers.Text: Because you need the actual html element in order to bind events
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-06-09T15:21:32.870Z
Answers.Text: I'm really slow at this. The `Garnish.MyAwesomeField = Garnish.Base.extend...` stuff goes in my `src/resources/occurrencesField.js` which is where the button click js lived, and all that button-click js just goes inside the skeleton clickEvent you provided?
Answers.UserDisplayName: kr37
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-06-09T15:33:32.973Z
Answers.Text: You can place the files wherever you like. There are no restrictions. I'm not sure what a `button-click` js is. You'll need to attach an accessible function as event listener to your button. The most elegant way to do this on global level is within a garnish class like I showed. It doesn't matter where that garnish class is or where it comes from. This is actually the only about js scopes and how you should always use Javascript - not really about Craft
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-06-12T18:21:26.240Z
Answers.Text: Yes, it's been almost 3 years since I've done any javascript, and wrapping my mind around the interplay between php and javascript has taken me a while to remember. Thank you so much for all the help! This part is more or less working. Now on to the controller!
Answers.UserDisplayName: kr37
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-24T07:20:41.410Z
Answers.LastActivityDate: 2018-05-24T07:32:58.583Z
Answers.LastEditDate: 2018-05-24T07:32:58.583Z
Answers.UserDisplayName: Robin Schambach
Body: <p>Updating a plugin from Craft 2 to Craft 3, so this logic used to work.</p>
  
  <p>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.</p>
  
  <p>The field's class seems to register the js correctly. When the page loads, it gives a popup with the correct info.</p>
  
  <pre><code>var startDateFieldHandle = 'fields-startDate';
  alert( 'startDateFieldHandle = '+startDateFieldHandle);
  </code></pre>
  
  <p>Above that is
  <code>&lt;script src="http://f.dev/cpresources/6991e452/occurrencesField.js?v=1527142206"&gt;&lt;/script&gt;</code>
  which pulls in the following:</p>
  
  <pre><code>jQuery(document).ready(function(){
      $("#fields-cal37_choose_dates_button").click( function() { 
          alert('Clicked the button');
  ...
          var start_date = new Date( jQuery("#"+startDateFieldHandle).val() );
  </code></pre>
  
  <p>The alerts happen in the correct sequence, but nevertheless my guess is that because <code>&lt;script cpresources&gt;</code> bit occurs earlier on the page than where <code>startDateFieldHandle</code> is set, that somehow it still isn't set when the button is clicked.</p>
  
  <p>I don't see, using <code>Craft::$app-&gt;View-&gt;registerJs($js);</code> that there is any way to say "put this first."  </p>
  
  <p>It did used to work under Craft 2. Any tips? </p>
  
  <p><strong>Update</strong><br>
  At present, I'm seeing in <code>occurrencesField.js</code> that as soon as I reference the startDateFieldHandle variable in any way, such as <code>alert(startDateFieldHandle);</code> the script quits.</p>
  
  <p>Also, in the Firefox console, I'm getting:</p>
  
  <pre><code>jQuery.Deferred exception: startDateFieldHandle is not defined @http://f.test/cpresources/6d6f7137/occurrencesField.js?v=1527518592:101:2
  l/&lt;/e@http://f.test/cpresources/61c13c0c/jquery.js?v=1527049453:1:29794
  l/&lt;/t&lt;@http://f.test/cpresources/61c13c0c/jquery.js?v=1527049453:1:30109
   undefined  jquery.js:1:31365
  Double-instantiating a menu button on an element garnish.js:1:2512
  </code></pre>
  
Tags: <plugin-development><javascript><custom-fieldtype><garnish>
Title: Plugin field-type not getting javascript variable?
ThreadText: # Plugin field-type not getting javascript variable?
  
  (Asked by: username_0 on 2018-05-24)
  
  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:
  
  ```
  jQuery(document).ready(function(){
      $("#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?
  
  **Update**  
  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
  l/</e@http://f.test/cpresources/61c13c0c/jquery.js?v=1527049453:1:29794
  l/</t<@http://f.test/cpresources/61c13c0c/jquery.js?v=1527049453:1:30109
   undefined  jquery.js:1:31365
  Double-instantiating a menu button on an element garnish.js:1:2512
  
  ```
  
  **Tags:** plugin-development, javascript, custom-fieldtype, garnish
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2018-05-24. Score: 2 | Accepted answer
  
  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 `"#"+startDateFieldHandle`unless 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
  
  ```
  jQuery("#fields-"+startDateFieldHandle)
  
  ```
  
  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() );
  
          }
      },
      {
          defaults:{
              fieldSelector: 'fields-',
              otherFieldHandle: ''
          }
      }
  );
  
  ```
  
  > **Comments:**
  > **username_0**: Sorry, I got pulled away a few days. Thank you so much, username_1, for the time and care you put into answering this question. I really appreciate it!  
  > **username_0**: 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.  
  > **username_0**: 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'`  
  > **username_1**: "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  
  > **username_0**: In your garnish.js, you use `this.$field`. Why not hardcode this as `this.fieldId` ?  
  > **username_1**: Because you need the actual html element in order to bind events  
  > **username_0**: I'm really slow at this. The `Garnish.MyAwesomeField = Garnish.Base.extend...` stuff goes in my `src/resources/occurrencesField.js` which is where the button click js lived, and all that button-click js just goes inside the skeleton clickEvent you provided?  
  > **username_1**: You can place the files wherever you like. There are no restrictions. I'm not sure what a `button-click` js is. You'll need to attach an accessible function as event listener to your button. The most elegant way to do this on global level is within a garnish class like I showed. It doesn't matter where that garnish class is or where it comes from. This is actually the only about js scopes and how you should always use Javascript - not really about Craft  
  > **username_0**: Yes, it's been almost 3 years since I've done any javascript, and wrapping my mind around the interplay between php and javascript has taken me a while to remember. Thank you so much for all the help! This part is more or less working. Now on to the controller!  
  
  ---
  
  