sutty-base-jekyll-theme/_packs/controllers/state_controller.js
Nulo 3a0c41b736 Limpiar eventos cuando el elemento o controlador que los escucha desaparece
Squashed commit of the following:

commit 482eea28821868f03ace33562e7bd34ab9a4478f
Merge: 5f48528 1c128f2
Author: f <f@sutty.nl>
Date:   Thu Nov 25 18:31:35 2021 -0300

    Merge branch 'master' into limpiar-eventos

commit 5f48528c28b0709bd859a4dc52a830f60bfedc6e
Author: f <f@sutty.nl>
Date:   Thu Nov 25 18:23:23 2021 -0300

    pretty

commit 70d05bc90a6cb64d1c4bfc39f48388af3fbc3c18
Merge: c4f33c0 ff1bc21
Author: Nulo <nulo@sutty.nl>
Date:   Thu Oct 28 16:46:31 2021 -0300

    Merge branch 'master' into limpiar-eventos

commit c4f33c084058002a10fc0ec2137ffe045826cfd2
Author: f <f@sutty.nl>
Date:   Thu Oct 28 14:52:41 2021 -0300

    limpiar eventos
2021-11-25 21:40:44 +00:00

115 lines
3.3 KiB
JavaScript

import { CartBaseController } from "./cart_base_controller";
/*
* Populates a state field where users can type to filter and select
* from a predefined list. It waits for an `cart:country:update` event
* to become populated.
*/
export default class extends CartBaseController {
// All are required!
static targets = ["id", "list", "name"];
connect() {
this.cart_country_update_event = this._cart_country_update_event.bind(this);
this.change_event = this._change_event.bind(this);
window.addEventListener(
"cart:country:update",
this.cart_country_update_event
);
// When the input changes we update the actual value and also the
// state list via an Event
this.nameTarget.addEventListener("change", this.change_event);
}
disconnect() {
window.removeEventListener(
"cart:country:update",
this.cart_country_update_event
);
this.nameTarget.removeEventListener("change", this.change_event);
}
async _cart_country_update_event(event) {
if (this.data.get("group") !== event.detail.group) return;
this.idTarget.value = "";
this.nameTarget.value = "";
this.listTarget.innerHTML = "";
const statesRequired = event.detail.data.statesRequired == "true";
this.nameTarget.disabled = !statesRequired;
this.nameTarget.required = statesRequired;
if (!statesRequired) return;
const states = await this.states(event.detail.iso);
const site = window.site;
states.forEach((state) => {
let option = document.createElement("option");
option.value = state.attributes.name;
option.dataset.id = state.id;
this.listTarget.appendChild(option);
});
this.nameTarget.pattern = states.map((x) => x.attributes.name).join("|");
this.nameTarget.addEventListener("input", (event) =>
this.nameTarget.setCustomValidity("")
);
this.nameTarget.addEventListener("invalid", (event) =>
this.nameTarget.setCustomValidity(site.i18n.states.validation)
);
if (event.detail.selectedState) {
this.nameTarget.value = event.detail.selectedState;
this.nameTarget.dispatchEvent(new Event("change"));
}
}
_change_event(event) {
const options = Array.from(this.listTarget.options);
const option = options.find((x) => x.value == this.nameTarget.value);
// TODO: If no option is found, mark the field as invalid
if (!option) return;
this.idTarget.value = option.dataset.id;
this.idTarget.dispatchEvent(new Event("change"));
}
/*
* Fetch the state list from storage or from API using a country ISO
* code
*/
async states(countryIso) {
const stateId = `states:${countryIso}`;
let states = JSON.parse(this.storageTemp.getItem(stateId));
if (states) return states;
// There's no state query, but we can fetch the country and include
// its states.
const response = await this.spree.countries.show(countryIso, {
include: "states",
});
// TODO: Show error message
if (response.isFail()) {
this.handleFailure(response);
return {};
}
states = response.success().included;
// Order alphabetically by name
states.sort((x, y) => x.attributes.name > y.attributes.name);
this.storageTemp.setItem(stateId, JSON.stringify(states));
return states;
}
}