camstuart

camstuart

Synopsis

I am trying to understand the correct approach for capturing data returned from a JS call to a third party, and ensuring it finds it’s way to my database. The page and form is in live view, and I would like to avoid breaking form validation or upsetting the live view life cycle.

NB: I played around with Phoenix ~4 years ago, and enjoyed it, but had to work on other technologies since.
I am back now, and intend to work with Elixir and Phoenix more seriously for a large side project.

Requirement I am implementing

I have a live view page that lists ‘locations’. To the UI, these are names, (EG: Home) and addresses.

To the backend, locations are all of the address constituents plus geometry (lat/lon). I have already setup PostGIS and geometry fields to capture this data enrichment.

At the bottom of the list of locations is a form to add new locations.

I have opted to obtain the geocoded address data from the front end in this case, simply because the library that gives me address autocomplete, returns the geocoded data in it’s response which is very convenient.

Running some sort of background job to geocode on the backend is less cost efficient in terms of the geocoding service, and would be wasted effort.

I have added javascript to app.js to perform ‘address autocomplete’ with the placekit.io service

As you can see from this javascript, I am using a very old (like me) web development trick where I set these values returned in the placekit api callback, into hidden field values.

function initPlaceKitAutocomplete() {
  const input = document.getElementById('lookup-address-input');
  if (input) {
    const pka = placekitAutocomplete('apikey-nothing-to-see-here', {
      target: '#lookup-address-input', // the 'id' in the HEEx <.input>
    });

    pka.on('pick', (value, item, index) => {
      console.log('pick', value, item, index);
      console.log('full address data', item);
      document.getElementById('latitude').value = item.lat;
      document.getElementById('longitude').value = item.lng;
    });
  }
}

document.addEventListener('DOMContentLoaded', function() {
  loadPlaceKitAPI(initPlaceKitAutocomplete);
});

The idea being that the data will then be available in the form changeset on submission (I hope)

Question

Is this a reasonable / best practice approach? It feels hacky.

I have a sense that it would be possible (and perhaps cleaner, although more work) to have the pka.on event update the form changeset by speaking directly to the live view component somehow (and perhaps not require hidden input fields?)

So the UI would send the geocoded data to the backend, which would in turn cause live view to update the UI. :thinking:

I would be very grateful for any advice on design and or implementation.

Thanks for reading :slight_smile:

PS: Happy to add template and elixir for context if that helps

Showing Posts 1 to 3

LostKobrakai

LostKobrakai

I‘d just use the hidden inputs and leave the frontend decoupled from the backend. No need to change anything on the backend if you decide down the line that you want to use some other method of populating the form.

I‘d suggest to question what makes the location selection different from any other form input, so that it should get special treatment.

Edit: You want to create a change event on those inputs though to make phx-change pick up on the updated values. Setting just the values on the DOM nodes from js doesn‘t do that automatically as you might want to change the value without triggering a change event.

03juan

03juan

Since you want to integrate as much as possible with the LiveView lifecycle, this sounds like a good use-case for a Client Hook

  • No need for the DOMContentLoaded listener
  • attach hook directly on the input <input type="search" name="place" placeholder="Search place..." class="input w-full" id="placekit-input" phx-hook="PlaceKit">
  • all logic can go in mounted() callback
    • use {target: this.el} in options
    • save the client in the hook object this.pka = placekit kautocomplete(...)
    • send data to the server in the callback this.pka.on("pick", (_, item, _) => this.pushEvent("picked", {item})
  • update the UI in server assigns after receiving the event
  • call this.pka.destroy() in the hook’s destroyed() callback

Bonus if you want to vendor/code-split the autocomplete-js library, you can dynamically import the library in your mounted() cb then use it to instantiate the client object. Keep app.js lean for the pages that don’t need this feature.

camstuart

camstuart OP

Thankyou @LostKobrakai and @03juan for your responses. They are both very helpful.
I’ll play around with both approaches, I think that will give me a better understanding of what live view can do, and what is suitable in this case

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
rahultumpala
Hello, I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews