How to pass a selected value from a simple_form to Stimulus controller

778 views Asked by At

Maybe I could start solving this if I understood where a select from a dropdown is stored/available in a Rails app. Then I have to move get it to the Stimulus controller. Complicated (at least for me) because the information is an image stored with Active Storage.

Want the doc.image to update when selected. The image is displayed on the page for 'edit' with an existing doc; but doesn't change the newly selected doc nor for 'new' items. (The table is named 'years' because they are tied to dates. Confusing choice of table name.)

class Doc has_one_attached :image . How to retrieve that image address (on AWS).

docUrl is available the edit of an existing year but does not get updated when a new doc is selected in the html.erb below.

html.erb for both edit and new

<div> <%= docUrl = url_for(@year.doc.image) %></div>
<div> <%= doc_image_width = @year.doc.image.metadata['width'] %>,  <%= doc_image_height = @year.doc.image.metadata['height'] %></div>
<div data-controller="snippet-draw"
     data-snippet-draw-url-value="<%= docUrl %>"
     data-snippet-draw-width-value="<%= doc_image_width %>"
     data-snippet-draw-height-value="<%= doc_image_height %>"
  >
  <!-- For Stimulus -->
  <%= form.association :doc,
      label_method: :id_page,
      collection: Doc.all,
      value_method: :id,
      label: "Select document(s) that support this",
      class: "fw-bold",
      input_html: { data: { action: "change->snippet-draw#addDoc" } }
  %>
  <input id="snippet_coords" data-snippet-draw-target="snippetCoords" type="text" >
</div>

app/javascript/controllers/snippet_draw_controller.js. This should only be relevant up through the first few lines connect method as the change (docURL) should be known then. Only the first import is relevant to the problem.

  import { Controller } from "@hotwired/stimulus"

  import Map from 'ol/Map';
  import View from 'ol/View';
  import Polygon from 'ol/geom/Polygon';
  import Draw, {createRegularPolygon, createBox} from 'ol/interaction/Draw';
  import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
  import ImageLayer from 'ol/layer/Image';
  import {OSM, Vector as VectorSource} from 'ol/source';
  import Static from 'ol/source/ImageStatic';
  import Projection from 'ol/proj/Projection';
  import {getCenter} from 'ol/extent';

  // Connects to data-controller="snippet-draw"
  export default class extends Controller {
    static targets = [ "snippetCoords"] // data-snippet-display-target="smap" Don't need map target

    static values = {
      url: String,
      width: Number,
      height: Number,
      docId: String,
    } // values

    addDoc(){
       const docId = this.docIdValue; // Retrieve the docId value
       const url = this.urlValue; // Retrieve the image URL value 
        // Once I get the url and other variables, can pass to connect with `this.connect();` I think
       connect(){
            const docURL = this.urlValue;
            const docWidth  = this.widthValue;
            const docHeight = this.heightValue;
            const extent = [0, 0, docWidth, docHeight];
            console.log(`44. ${Date.now()} docURL:  ${docURL}`)

            let source = new VectorSource(); 

            let drawLayer = new VectorLayer({
              source: source
            });    

            let projection = new Projection({
              units: 'pixels',
              extent: extent,
            });

            let docSource = new Static({
              attributions: '',
              url: docURL,
              projection: projection,
              imageExtent: extent
            });

            let docLayer = new ImageLayer({ 
              source: docSource,
              extent: extent,
            });

            let staticView = new View({
              projection: projection,
              center: getCenter(extent),
              zoom: 2.5, 
              maxZoom: 4,
            });

            let map = new Map({
              layers: [docLayer],
              target: 'snmap',
              view: staticView,
              extent: extent,
            });

            function getSnippetCoordinates(coordsOutputTarget) {
              let draw = new Draw({
                source: source,
                type: 'Circle',
                geometryFunction: createBox()
              });
              map.addInteraction(draw);
               draw.on('drawend', function(event) {
                   let boxCoords = event.feature.values_.geometry.flatCoordinates;
                 let boxCoordsStringified = JSON.stringify(boxCoords);
                 let boxCoordsStringifiedParsed = JSON.parse(boxCoordsStringified);
                 var truncCoords = function(element,index,array){
                   return Math.trunc(element);
                 };
                 boxCoordsStringifiedParsedMap = boxCoordsStringifiedParsed.map(truncCoords);
                 document.getElementById('year_snippet_coords').innerHTML = boxCoordsStringifiedParsedMap; 
               });
               }

            const someText = "Drawn coordinates will appear here after drawing a rectangle. (From snippet_draw_controller:113. Dev only since don't get added to dB";
            this.snippetCoordsTarget.textContent = `${someText}`;
            getSnippetCoordinates(this.snippetCoordsTarget);
            } // end connect    
          } 
      }
0

There are 0 answers