Jump to content

RockCalculator: Add a calculator to any Inputfield in the ProcessWire backend.


bernhard
 Share

Recommended Posts

RockCalculator

Add a calculator to any Inputfield in the ProcessWire backend.

img

Setup

At the moment there is no UI for defining fields that should support the calculator. You have multiple options:

  1. Tracy Console
// show rockcalculator and round result to .00
$field = $fields->get('yourfieldname');
$field->set('rockcalculator', 2); // 2 digit precision
$field->save();
  1. RockMigrations
$rm->setFieldData('yourfield', ['rockcalculator' => 2]);
  1. Hook buildForm
$wire->addHookAfter("ProcessPageEdit::buildForm", function($event) {
  $form = $event->return;
  $page = $event->process->getPage(); // edited page
  if($page->template !== 'yourpagetemplate') return;
  if($f = $form->get('yourfield1')) $f->rockcalculator = 2;
  if($f = $form->get('yourfield2')) $f->rockcalculator = 2;
  if($f = $form->get('yourfield3')) $f->rockcalculator = 2;
});
  • Like 13
Link to comment
Share on other sites

  • 1 year later...

This looks a handy little module. I'm hoping to add it as an enhancement to my FieldtypeMeasurement module, which it would complement very nicely. However, I'm scratching my head a bit as to the best way of incorporating it as I really need to embed it within my Inputfield::render() method  - i.e. after the hook in your module has fired (?), but I think that's too late.

The problem is that my field is an object. The magnitude property (which is where I'd like the calculator) is rendered as a text inputfield. So what I was hoping to do was something like this (where $f will be the inputfield for the magnitude): 

$f = $this->modules->get("InputfieldText");
			if(wire()->modules->isInstalled('RockCalculator')) {
				// set the rockcalculator here //
				$f->attr("data-rockcalculator", 6); //6 digit precision
				$f->notes = __("Numeric or math formula");
			} else {
				$f->notes = __("Numeric");
				$f->precision = 6;
				$f->attr('type', "number");
				$f->attr('step', "any");
			}

However, that doesn't work because the assets aren't loaded. It works OK if I remove the line

if(!$this->isEnabled($inputfield)) return;

from loadAssets(), but obviously if the module is used elsewhere in the site, that is not a great idea and isEnabled() is not hookable. I could just load the assets separately, I guess. Any suggestions@bernhard

  • Like 1
Link to comment
Share on other sites

I think you just need to set the property "rockcalculator" of your field (not inputfield!) before it is rendered. That should be possible from your code without any hooks. Maybe like this?

<?php
$f = $this->modules->get("InputfieldText");
if(wire()->modules->isInstalled('RockCalculator')) {
  // set the rockcalculator here //
  $f->attr("data-rockcalculator", 6); //6 digit precision
  $f->notes = __("Numeric or math formula");
  $f->hasField->rockcalculator = true;
} else {
  $f->notes = __("Numeric");
  $f->precision = 6;
  $f->attr('type', "number");
  $f->attr('step', "any");
}

 

  • Like 1
Link to comment
Share on other sites

Thanks @bernhard. That's helpful but doesn't work as $f->hasField is null because magnitude is a property of a measurement object field, not a field itself. So I tried the following code - creating a dummy field to hold the rockcalculator property: 

			$f = $this->modules->get("InputfieldText");
			if(wire()->modules->isInstalled('RockCalculator')) {
				$f->attr("data-rockcalculator", 6); //6 digit precision
				$f->notes = __("Numeric or math formula");
				$dummyField = wire()->fields->makeItem(['name' => 'dummyName']);
				$f->hasField = $dummyField;
				$f->hasField->rockcalculator = true;
				bd($f, '$f in rockcalc');
			} else {
				$f->notes = __("Numeric");
				$f->precision = 6;
				$f->attr('type', "number");
				$f->attr('step', "any");
			}

That almost works, in the sense that isEnabled() is true and loadAssets() runs. However the dev tools do not show the js as loaded and the field doesn't work.

I've got round the problem by including the following in the init() of my fieldtype module:

		if(wire()->modules->isInstalled('RockCalculator')) {
			$rc = $this->wire->modules->get('RockCalculator');
			$this->wire->config->scripts->add($rc->m('lib/math.min.js'));
			$this->wire->config->scripts->add($rc->m('lib/tooltip.js'));
			$this->wire->config->scripts->add($rc->m($rc->className . '.js'));
			$this->wire->config->styles->add($rc->m($rc->className . '.css'));
		}

Maybe there is a better way, but at least this seems to work.

And your module certainly enhances mine ☺️

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...