Thank you for your comments on my two posts. Sorry I have not replied earlier. You got me thinking on the multiple controller question and I’ve rewrote it with one controller.
This was my simple inventory calculator. The page looks like
This is not even in a database, it’s just a yaml file. I can download a ‘Quantity on hand’ csv file from my POS and I merge it with my last physical inventory. I then update each item using this calculator. The single controller is on the form of both the liquor and beer edit pages. This is a true calculator like function in that any target field that changes computes the total field, which is how many bottle of beer or shots (1.25 ounces) of liquor I have. I’m taking inventory using a iPad so each item changed checks a check box that that item was at least counted.
Again, I did the multiple controller because of trying to find the targets on each row - I figured out a way to do that!.
The new inventory_controller.js file:
/*
Rails.root/app/javascript/controllers/inventroy-controller.js
*/
import { Controller } from "stimulus"
export default class extends Controller {
static targets = [ 'bottles',"wbottles", "cbottles","cases",'total','size','percent','ckd']
connect() {
this.idx
}
indexOfTargetInTargets(target,targets){
var i
for (i = 0; i < targets.length; i++) {
if (targets[i] == target) {break}
}
return i
}
updateBeer(){
var beer = event.target
const beerTarget = beer.dataset.target.replace('inventory.','')
const beerTargets = eval(`this.${beerTarget}Targets`)
this.idx = this.indexOfTargetInTargets(beer,beerTargets)
this.totalTargets[this.idx].value = this.wbottles + this.cbottles + (this.cases * this.size )
this.ckdTargets[this.idx].checked = true
}
updateLiquor(){
var liquor = event.target
const liquorTarget = liquor.dataset.target.replace('inventory.','')
const liquorTargets = eval(`this.${liquorTarget}Targets`)
this.idx = this.indexOfTargetInTargets(liquor,liquorTargets)
const shots = ((this.size * (this.percent / 100.0)) / 35.5)
const bottles = ((this.bottles * this.size) / 35.5)
this.totalTargets[this.idx].value = Math.round(bottles + shots)
this.ckdTargets[this.idx].checked = true
}
get cases(){
return Number(this.casesTargets[this.idx].value)
}
get wbottles(){
return Number(this.wbottlesTargets[this.idx].value)
}
get cbottles(){
return Number(this.cbottlesTargets[this.idx].value)
}
get size(){
return Number(this.sizeTargets[this.idx].value)
}
get bottles(){
return Number(this.bottlesTargets[this.idx].value)
}
get percent(){
return Number(this.percentTargets[this.idx].value)
}
}
Here’s what happens
- The connect() method defines what I guess is a global controller variable idx ( or index)
- The updateBeer and updateLiquor functions are the only actions and are called if any input field is changed
- I get the event target and then get the dataset.target value and strips off the controller name leaving just the target name
- I then build a
this.{name}Targetsstring and call eval the get the target for whatever target generated the event - I then get the index of the target in the Targets array by calling my function
indexOfTargetInTargets(target,targets)which sets the global this.idx - It then does the calculation by calling the getters which use this.idx and sets the total field and checks the check box
A single controller that, while there a multiple targets, just focus on one row.
Maybe stimulus has a build in function to get the index of a target but I couldn’t find it. If there is one, someone let me know
This one was pretty simple in that I didn’t get an sum for each column. I can with this approach. Didn’t think about end-of-year inventory, but that’s simple with this single controller approach.
I reply to the other post(golf scoring) in a few days. Looking into if can use the idx scheme there.
