Sage 9 - calling / use javascript custom functions / classes in template

I looked at some posts on the subject but I’m stuck :frowning:

I added a new sample.js file with one function getMileage() and one class Car with static function getSpeed() in resources/assets/scripts/sample.js

They were getting compiled into the sample.js file but I couldn’t use function in template (note: they are loaded and the log output is displayed in the JS console. Also calling in commons.js works!)

My questions:

  • What do I do so that I can invoke the JS class in the blade template (example header-blade-php)?
  • What am I doing wrong?
<script>
  console.log('TEMPLATE :: script::template::begin');
  // example here
  // ???????
  // Car.getSpeed();
  console.log('TEMPLATE :: script::template::end');
</script>

I am using sage 9.0.0-beta-4, my problem may be independent of the saga version.

Here sample.js, setup.php, common.js

/* eslint no-undef: 0 */
/* eslint no-unused-vars:0 */

console.log('JS :: sample.js');

export function getMileage() {
  console.log('sample.js # getMileage()');
  return '45.678 km';
}

export class Car {
  static getSpeed() {
    console.log('sample.js # Car :: getSpeed()');
    return '100 km/h';
  }
}

I have made the following adjustments

  1. add sample.js in app/setup.php
add_action('wp_enqueue_scripts', function () {
    wp_enqueue_style('sage/main.css', asset_path('styles/main.css'), false, null);
    wp_enqueue_script('sage/main.js', asset_path('scripts/main.js'), ['jquery'], null, true);
    wp_enqueue_script('sage/sample.js', asset_path('scripts/sample.js'), [], null, true);
}, 100);
  1. add sample.js in resources/assets/config.json
{
  "entry": {
    "main": [
      "./scripts/main.js",
      "./styles/main.scss"
    ],
    "customizer": [
      "./scripts/customizer.js"
    ],
    "sample": [
      "./scripts/sample.js"
    ]
  },
  "publicPath": "/wp-content/themes/wp-sample",
  "devUrl": "http://localhost:8080",
  "proxyUrl": "http://localhost:3000",
  "cacheBusting": "[name]_[hash:8]",
  "watch": [
    "app/**/*.php",
    "config/**/*.php",
    "resources/controllers/**/*.php",
    "resources/views/**/*.php"
  ]
}
  1. my common.js in resources/assets/scripts/routes/common.js looks like this
import { Car, getMileage } from '../sample';

export default {
  init() {
    // JavaScript to be fired on all pages
    console.log('common.js init() --> ' + Car.getSpeed());
    console.log('common.js init() --> ' + getMileage());
  },
  finalize() {
    // JavaScript to be fired on all pages, after page specific JS is fired
  },
};

I have solved my problem. Sorry for the post but maybe it will help someone else.

My changes for function getMileage() compared to the previous version (now with namespace)

sample.js in resources/assets/scripts/sample.js

const SAMPLE = SAMPLE || (function() {
  return {
    getMileage : function() {
      console.log('sample.js # getMileage()');
      return '45.678 km';
      }
    },
  };
}());

export default SAMPLE;

common.js in resources/assets/scripts/routes/common.js

import SAMPLE from '../sample';

export default {
  init() {
    // JavaScript to be fired on all pages
    window.SAMPLE = SAMPLE;
  },
  finalize() {
    // JavaScript to be fired on all pages, after page specific JS is fired
  },
};

template

<script>
SAMPLE.getMileage();
</script>
2 Likes

Any specific reason you chose this solution? Would it not be better with car/mileage container divs with data attributes that you can iterate over in the js?

1 Like