fceruti

fceruti

In a nutshell the issue I’m facing is that every time I register alpine’s @ or x-on event handler, two are registered and called when the action is performed.

The issue is solved if I comment liveSocket.connect(), which leads me to believe the problem is in the interoperation of liveSocket and Alpine.

I’ve circled the internet without success. Has anyone had this issue and solved it?

Packages:
Phoenix: 1.6.2
Phoenix Live View: 0.16.4
Surface: 0.6.1
Alpinejs: 3.3.5 & 3.4.2

Surface component:

defmodule TimetaskApp.WeekCalendar do
  use Surface.LiveComponent

  prop hours, :list, required: true

  prop dates, :list, required: true

  @impl true
  def render(assigns) do
    ~F"""
    <div class="w-full h-full flex flex-col" style="height: calc(100vh - 100px)" id="week-calendar">  {!-- Calendar --}
      <div class="h-full flex-1 flex flex-row relative">
        <div
          class="flex-1 flex"
          id="week-calendar-columns"
          :hook="WeekCalendar"
          x-init="fromHour = +$el.dataset.fromHour; toHour = +$el.dataset.toHour;"
          x-data="week_calendar_data"
          data-from-hour={List.first(@hours)}
          data-to-hour={List.last(@hours)}
        >
          <div
            class="flex-1 flex"
            id="week-calendar-days-container"
            x-ref="days_container"
          >
            {#for date <- @dates}
              <div
                id={"day_col_#{format_date(date)}"}
                data-date={format_date(date)}
                class="flex-1 border-r border-tt-border-calendar relative"
                @mousedown.stop="startNewTimebox($event, $el.dataset.date)"
              >
              </div>
            {/for}
          </div>
        </div>
      </div>
    </div>
    """
  end
end

app.js:

import { Socket } from "phoenix"
import { LiveSocket } from "phoenix_live_view"
import topbar from "topbar"
import Alpine from "alpinejs"
import Hooks from "./_hooks"

import "./app/week_calendar.js"

window.Alpine = Alpine
Alpine.start()

let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {
  params: { _csrf_token: csrfToken },
  hooks: Hooks,
  dom: {
    onBeforeElUpdated(from, to) {
      if (from._x_dataStack) {
        window.Alpine.clone(from, to)
      }
    },
  },
});

topbar.config({ barColors: { 0: "#03ad8c" }, shadowColor: "rgba(0, 0, 0, .3)" })
window.addEventListener("phx:page-loading-start", info => topbar.show())
window.addEventListener("phx:page-loading-stop", info => topbar.hide())

liveSocket.connect()
window.liveSocket = liveSocket

./app/week_calendar.js

document.addEventListener("alpine:init", () => {
  Alpine.data("week_calendar_data", () => ({
    fromHour: 0,
    toHour: 0,
    newTimebox: null,
    startNewTimebox(event, date) {
      const fromTime = this.getTimeFromEvent(event)
      this.newTimebox = {
        date: date,
        fromTime: fromTime,
        toTime: null
      }
      console.log(`Start new timebox ${date} ${fromTime.hour}:${fromTime.minute}`)
    },
  }))
});

Chrome dev tools:

Chrome console:
Screen Shot 2021-11-04 at 03.59.51

Showing Posts 1 to 10

seanc

seanc

Does it work if you get rid of Alpine.start()? Importing might automatically start it.

fceruti

fceruti OP

Nothing happens, the event handlers are not present. Alpine is not started in the import.

cmo

cmo

You got an x-data on that div, or its parent?

fceruti

fceruti OP

Yes there is, I updated my original post to show more context.

cmo

cmo

what’s the rendered html look like for the bit inside {#for date <- @dates}?

fceruti

fceruti OP

This is the page full html (ps: I made a few updates to the original post)

view-source:127.0.0.1:4000/app/calendar

<div data-phx-main="true" data-phx-session="SFMyNTY.g2gDaAJhBXQAAAAIZAACaWRtAAAAFHBoeC1GclJGMEZlRS1DVVB2UktCZAAMbGl2ZV9zZXNzaW9uaAJkAAdkZWZhdWx0bggAUIScpgUdtBZkAApwYXJlbnRfcGlkZAADbmlsZAAIcm9vdF9waWRkAANuaWxkAAlyb290X3ZpZXdkAB9FbGl4aXIuVGltZXRhc2tBcHAuTGl2ZUNhbGVuZGFyZAAGcm91dGVyZAAZRWxpeGlyLlRpbWV0YXNrV2ViLlJvdXRlcmQAB3Nlc3Npb250AAAAAGQABHZpZXdkAB9FbGl4aXIuVGltZXRhc2tBcHAuTGl2ZUNhbGVuZGFybgYAzjTB6XwBYgABUYA.gQQA8Bf1ScKf-xpokXsCPC48M9lqLWwb6Won9BzCkpA" data-phx-static="SFMyNTY.g2gDaAJhBXQAAAADZAAKYXNzaWduX25ld2wAAAACZAALX19jb250ZXh0X19kAAtfX3N1cmZhY2VfX2pkAAVmbGFzaHQAAAAAZAACaWRtAAAAFHBoeC1GclJGMEZlRS1DVVB2UktCbgYAzjTB6XwBYgABUYA.GBBwOY7Xtgbxw51hEzU0mvpHuSMM9realSNQyzeoL8A" id="phx-FrRF0FeE-CUPvRKB"><!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="NWVsPwERIkA3IUFBJwc_FVxgFUh7ZGFPw2YeXgo-AY3vO3kRo1w1LU9w" name="csrf-token">
<title>Calendar</title>
    <link phx-track-static rel="stylesheet" href="/assets/app.css">
    <script defer phx-track-static type="text/javascript" src="/assets/app.js"></script>
  </head>
  <body>
    <div class="flex flex-col min-h-screen max-h-screen select-none overflow-hidden bg-gray-0">
    <nav>
  <div class="px-4">
    <div class="grid grid-cols-6 h-16 items-center">
      <div class="col-span-2">
        <div class="flex items-center">
          <a class="block h-6 w-auto mr-8 ml-2" href="/app/calendar">
            <svg width="100%" height="100%" viewBox="0 0 606 123" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule: evenodd; clip-rule: evenodd; stroke-linejoin: round; stroke-miterlimit: 2; max-height: 100px">
    <g transform="matrix(1,0,0,1,-196,-237)">
        <g id="Layer-1" serif:id="Layer 1">
            <g transform="matrix(1,0,0,1,219.121,343.75)">
                <path d="M0,-37.498L0,-51.124L-19.121,-51.124L-19.121,-36.216C-19.121,-8.689 3.195,13.626 30.722,13.626L33.105,13.626L33.105,-5.22L30.722,-5.22C13.755,-5.22 0,-20.531 0,-37.498" style="fill: rgb(65,65,91); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(1,0,0,1,0,31.156)">
                <rect x="269.411" y="242.624" width="18.583" height="83.596" style="fill: rgb(65,65,91)"></rect>
            </g>
            <g transform="matrix(1,0,0,1,270.098,244.227)">
                <path d="M0,5.141C2.361,7.504 5.335,8.752 8.604,8.752C12.004,8.752 15.139,7.415 17.433,4.988C19.645,2.645 20.814,-0.329 20.814,-3.611L-3.605,-3.611C-3.605,-0.242 -2.356,2.786 0,5.141" style="fill: rgb(65,65,91); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(1,0,0,1,530.42,332.174)">
                <path d="M0,-58.394L-0.012,-83.574L-14.114,-83.574L-14.114,-13.575C-14.114,7.833 3.256,25.18 24.664,25.152L24.664,10.962C11.097,10.962 0.094,-0.026 0.076,-13.594L0.042,-35.514L0.013,-35.514L0.008,-44.286L24.664,-44.303L24.664,-58.394L0,-58.394Z" style="fill: rgb(65,65,91); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(1,0,0,1,621.528,294.74)">
                <path d="M0,41.689C-5.881,47.527 -12.813,50.366 -21.195,50.366C-29.487,50.366 -36.398,47.523 -42.329,41.677C-48.26,35.832 -51.144,28.969 -51.144,20.701C-51.144,12.53 -48.26,5.716 -42.329,-0.131C-36.396,-5.977 -29.484,-8.82 -21.195,-8.82C-12.815,-8.82 -5.883,-5.981 0,-0.143C5.89,5.705 8.753,12.524 8.753,20.701C8.753,28.977 5.89,35.843 0,41.689M8.753,-10.612C6.857,-12.442 4.771,-14.12 2.496,-15.639C-4.651,-20.406 -12.718,-22.822 -21.487,-22.822C-33.529,-22.822 -43.964,-18.528 -52.498,-10.061C-61.023,-1.603 -65.347,8.746 -65.347,20.701C-65.347,32.748 -61.027,43.166 -52.51,51.668C-43.975,60.19 -33.538,64.511 -21.487,64.511C-12.712,64.511 -4.644,62.093 2.496,57.328C4.771,55.809 6.857,54.128 8.753,52.289L8.753,62.636L22.958,62.636L22.958,-20.96L8.753,-20.96L8.753,-10.612Z" style="fill: rgb(65,65,91); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(1,0,0,1,698.696,318.45)">
                <path d="M0,-5.731L-9.553,-8.785L-23.552,-13.258C-30.075,-15.25 -30.955,-18.171 -30.955,-20.765C-30.955,-23.668 -29.424,-26.28 -26.271,-28.751C-22.831,-31.45 -18.06,-32.819 -12.089,-32.819C-5.425,-32.819 0.452,-30.794 5.877,-26.626L7.401,-25.455L17.594,-35.476L14.274,-37.826C6.11,-43.602 -3.154,-46.532 -13.265,-46.532C-22.449,-46.532 -30.188,-43.959 -36.268,-38.888C-42.581,-33.616 -45.783,-27.42 -45.783,-20.476C-45.783,-15.769 -44.191,-11.5 -41.052,-7.789C-38.021,-4.198 -33.571,-1.561 -27.972,0.008L-20.786,2.26L-4.478,7.372C5.015,10.342 5.015,14.275 5.015,15.755C5.015,16.681 5.015,19.494 0.148,22.954C-3.625,25.638 -8.299,26.943 -14.145,26.943C-29.364,26.943 -38.443,15.016 -38.443,15.016L-48.347,24.754C-48.347,24.754 -41.905,33.542 -31.205,37.707C-25.399,39.967 -19.088,40.801 -12.677,40.801C-3.822,40.801 3.74,38.35 9.802,33.512C16.171,28.433 19.4,22.312 19.4,15.323C19.4,8.351 16.018,-0.964 0,-5.731" style="fill: rgb(65,65,91); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(1,0,0,1,393.782,354.677)">
                <path d="M0,-80.06C-3.938,-81.834 -8.218,-82.759 -12.833,-82.759L-17.232,-82.759C-24.307,-82.759 -30.728,-80.586 -36.318,-76.298C-37.382,-75.483 -38.359,-74.607 -39.287,-73.698C-40.215,-74.607 -41.192,-75.483 -42.257,-76.298C-47.847,-80.586 -54.268,-82.759 -61.342,-82.759L-65.741,-82.759C-70.356,-82.759 -74.637,-81.834 -78.574,-80.06C-81.942,-78.542 -85.061,-76.411 -87.888,-73.613C-94.04,-67.523 -97.157,-60.079 -97.157,-51.486L-97.157,2.699L-78.577,2.699L-78.577,-50.763C-78.511,-54.483 -77.208,-57.53 -74.475,-60.23C-71.75,-62.923 -68.743,-64.178 -65.014,-64.178L-62.065,-64.178C-58.338,-64.178 -55.333,-62.923 -52.606,-60.228C-49.874,-57.53 -48.57,-54.483 -48.505,-50.763L-48.505,2.699L-30.07,2.699L-30.07,-50.763C-30.004,-54.483 -28.701,-57.53 -25.969,-60.228C-23.241,-62.923 -20.237,-64.178 -16.509,-64.178L-13.56,-64.178C-9.832,-64.178 -6.825,-62.923 -4.1,-60.23C-1.368,-57.53 -0.063,-54.483 0.003,-50.763L0.003,2.699L18.582,2.699L18.582,-51.486C18.582,-60.079 15.465,-67.523 9.313,-73.613C6.487,-76.411 3.367,-78.542 0,-80.06" style="fill: rgb(65,65,91); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(1,0,0,1,237.775,273.779)">
                <path d="M0,18.846L22.94,18.846L22.94,0L-18.655,0C-18.655,10.408 -10.409,18.846 0,18.846" style="fill: rgb(0,225,171); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(0,1,1,0,226.143,247.637)">
                <path d="M-7.021,-26.143L7.309,-26.143C17.717,-26.143 26.143,-17.431 26.143,-7.023L-7.021,-7.021L-7.021,-26.143Z" style="fill: rgb(0,173,140); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(1,0,0,1,759.544,273.773)">
                <path d="M0,34.359L34.099,0L-0.083,34.258L0,34.359Z" style="fill: rgb(65,65,91); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(1,0,0,1,759.461,297.945)">
                <path d="M0,10.086L34.182,-24.173L14.216,-24.173L-20.299,10.46L-20.299,-49.345L-34.54,-49.345L-34.54,59.431L-20.299,59.431L-20.299,30.725L0.083,10.187L0,10.086Z" style="fill: rgb(65,65,91); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(1,0,0,1,749.022,318.737)">
                <path d="M0,0.169L0.163,0.001L0.162,0L0,0.169Z" style="fill: rgb(65,65,91); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(1,0,0,1,800,318.5)">
                <path d="M0,38.876L-31.938,0L-50.581,0L-50.814,0.238L-18.875,38.876L0,38.876Z" style="fill: rgb(65,65,91); fill-rule: nonzero"></path>
            </g>
            <g transform="matrix(1,0,0,1,438.97,324.014)">
                <path d="M0,-16.859L0.038,-16.974C1.391,-21.066 3.689,-24.625 7.065,-27.852C12.295,-32.85 18.392,-35.278 25.7,-35.278C33.114,-35.278 39.285,-32.844 44.563,-27.837C47.959,-24.613 50.253,-21.06 51.577,-16.974L51.614,-16.859L0,-16.859ZM57.09,-39.418C48.954,-47.919 38.395,-52.229 25.704,-52.229C13.472,-52.229 2.975,-47.912 -5.496,-39.4C-13.938,-30.912 -18.22,-20.514 -18.22,-8.498C-18.22,3.593 -13.66,14.057 -4.668,22.604C4.24,31.075 15.157,35.37 27.778,35.37C35.241,35.37 42.318,33.75 48.813,30.556C52.824,28.581 56.545,26.044 59.871,23.014L59.974,22.92L47.704,10.65L47.614,10.561L47.521,10.646C45.533,12.457 43.338,13.931 40.811,15.151C36.772,17.1 32.509,18.047 27.778,18.047C20.221,18.047 13.875,15.63 8.379,10.66C4.913,7.526 2.554,4.108 1.168,0.213L0.795,-0.886L67.731,-0.886L67.755,-0.988C69.816,-9.405 69.249,-17.856 66.117,-25.427C63.912,-30.757 60.875,-35.465 57.09,-39.418" style="fill: rgb(65,65,91); fill-rule: nonzero"></path>
            </g>
        </g>
    </g>
</svg>


          </a>

          <nav class="flex gap-2">
            <a tabindex="-1" href="/app/calendar">
    <button class="inline-flex items-center rounded-md focus:outline-none transition duration-75 whitespace-nowrap disabled:cursor-not-allowed py-2 px-3 text-base gap-2 hover:text-brand-dark font-normal text-brand-regular fill-current" tabindex="-1" type="button">
    
    
              <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="fill-current" viewBox="0 0 24 24"><path d="M3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-2V2h-2v2H9V2H7v2H5a2 2 0 0 0-2 2zm16 14H5V8h14z"/></svg>
            
  
  </button>

</a>


            <a tabindex="-1" href="/app/projects">
    <button class="inline-flex items-center rounded-md focus:outline-none transition duration-75 whitespace-nowrap disabled:cursor-not-allowed py-2 px-3 text-base gap-2 hover:text-brand-dark font-normal text-tt-text fill-current" tabindex="-1" type="button">
    
    
              <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="fill-current" viewBox="0 0 24 24"><path d="M18.5 2h-12C4.57 2 3 3.57 3 5.5V22l7-3.5 7 3.5v-9h5V5.5C22 3.57 20.43 2 18.5 2zM15 18.764l-5-2.5-5 2.5V5.5C5 4.673 5.673 4 6.5 4h8.852A3.451 3.451 0 0 0 15 5.5v13.264zM20 11h-3V5.5c0-.827.673-1.5 1.5-1.5s1.5.673 1.5 1.5V11z"/></svg>
            
  
  </button>

</a>


            <a tabindex="-1" href="/app/reports">
    <button class="inline-flex items-center rounded-md focus:outline-none transition duration-75 whitespace-nowrap disabled:cursor-not-allowed py-2 px-3 text-base gap-2 hover:text-brand-dark font-normal text-tt-text fill-current" tabindex="-1" type="button">
    
    
              <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="fill-current" viewBox="0 0 24 24"><path d="M9 6h2v14H9zm4 2h2v12h-2zm4-4h2v16h-2zM5 12h2v8H5z"/></svg>
            
  
  </button>

</a>


          </nav>
        </div>
      </div>
      <div class="col-span-2 flex justify-center">
        
            <a data-phx-link="patch" data-phx-link-state="push" href="/app/calendar?date=today">
      <button class="inline-flex items-center rounded-md focus:outline-none transition duration-75 whitespace-nowrap disabled:cursor-not-allowed py-2 px-3 text-base gap-2 text-tt-text bg-transparent font-medium hover:bg-gray-50 hover:text-tt-text-dark active:text-brand-regular active:bg-transparent fill-current" tabindex="-1" type="button">
    
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="fill-current" viewBox="0 0 24 24"><path d="M13.293 6.293 7.586 12l5.707 5.707 1.414-1.414L10.414 12l4.293-4.293z"/></svg>
    
  </button>

  </a>

  <a data-phx-link="patch" data-phx-link-state="push" href="/app/calendar?date=today">
      <button class="inline-flex items-center rounded-md focus:outline-none transition duration-75 whitespace-nowrap disabled:cursor-not-allowed py-2 px-3 text-base gap-2 text-tt-text bg-transparent font-medium hover:bg-gray-50 hover:text-tt-text-dark active:text-brand-regular active:bg-transparent font-semibold w-52 justify-center" tabindex="-1" type="button">
    
      8 - 14 November
    
  </button>

  </a>

  <a data-phx-link="patch" data-phx-link-state="push" href="/app/calendar?date=2021-11-18">
      <button class="inline-flex items-center rounded-md focus:outline-none transition duration-75 whitespace-nowrap disabled:cursor-not-allowed py-2 px-3 text-base gap-2 text-tt-text bg-transparent font-medium hover:bg-gray-50 hover:text-tt-text-dark active:text-brand-regular active:bg-transparent fill-current" tabindex="-1" type="button">
    
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="fill-current" viewBox="0 0 24 24"><path d="M10.707 17.707 16.414 12l-5.707-5.707-1.414 1.414L13.586 12l-4.293 4.293z"/></svg>
    
  </button>

  </a>


        
      </div>
      <div class="col-span-2 flex justify-end">
        <div phx-hook="TimetaskApp.Components.Dropdown#Dropdown" class="relative inline-block text-left z-20" id="nav-dropdown">
    <button phx-click="toggle_dropdown" phx-target="4" class="inline-flex items-center rounded-md focus:outline-none transition duration-75 whitespace-nowrap disabled:cursor-not-allowed py-2 px-3 text-base gap-2 text-tt-text bg-transparent font-medium hover:bg-gray-50 hover:text-tt-text-dark active:text-brand-regular active:bg-transparent fill-current" tabindex="-1" type="button">
    
    
            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="fill-current" viewBox="0 0 24 24"><path d="M12 16c2.206 0 4-1.794 4-4s-1.794-4-4-4-4 1.794-4 4 1.794 4 4 4zm0-6c1.084 0 2 .916 2 2s-.916 2-2 2-2-.916-2-2 .916-2 2-2z"/><path d="m2.845 16.136 1 1.73c.531.917 1.809 1.261 2.73.73l.529-.306A8.1 8.1 0 0 0 9 19.402V20c0 1.103.897 2 2 2h2c1.103 0 2-.897 2-2v-.598a8.132 8.132 0 0 0 1.896-1.111l.529.306c.923.53 2.198.188 2.731-.731l.999-1.729a2.001 2.001 0 0 0-.731-2.732l-.505-.292a7.718 7.718 0 0 0 0-2.224l.505-.292a2.002 2.002 0 0 0 .731-2.732l-.999-1.729c-.531-.92-1.808-1.265-2.731-.732l-.529.306A8.1 8.1 0 0 0 15 4.598V4c0-1.103-.897-2-2-2h-2c-1.103 0-2 .897-2 2v.598a8.132 8.132 0 0 0-1.896 1.111l-.529-.306c-.924-.531-2.2-.187-2.731.732l-.999 1.729a2.001 2.001 0 0 0 .731 2.732l.505.292a7.683 7.683 0 0 0 0 2.223l-.505.292a2.003 2.003 0 0 0-.731 2.733zm3.326-2.758A5.703 5.703 0 0 1 6 12c0-.462.058-.926.17-1.378a.999.999 0 0 0-.47-1.108l-1.123-.65.998-1.729 1.145.662a.997.997 0 0 0 1.188-.142 6.071 6.071 0 0 1 2.384-1.399A1 1 0 0 0 11 5.3V4h2v1.3a1 1 0 0 0 .708.956 6.083 6.083 0 0 1 2.384 1.399.999.999 0 0 0 1.188.142l1.144-.661 1 1.729-1.124.649a1 1 0 0 0-.47 1.108c.112.452.17.916.17 1.378 0 .461-.058.925-.171 1.378a1 1 0 0 0 .471 1.108l1.123.649-.998 1.729-1.145-.661a.996.996 0 0 0-1.188.142 6.071 6.071 0 0 1-2.384 1.399A1 1 0 0 0 13 18.7l.002 1.3H11v-1.3a1 1 0 0 0-.708-.956 6.083 6.083 0 0 1-2.384-1.399.992.992 0 0 0-1.188-.141l-1.144.662-1-1.729 1.124-.651a1 1 0 0 0 .471-1.108z"/></svg>
          
  
  </button>


  
</div>

      </div>
    </div>
  </div>
</nav>



  <div class="full-width-container">
    <div class="w-full h-full flex flex-col" style="height: calc(100vh - 100px)" id="week-calendar">  
  <div class="flex h-10 w-full">  
    <div class="h-10 calendar-head" style="width: 40px"></div>
    <div class="h-10 flex-1 flex">
      
        <div class="flex-1 flex justify-center items-end pb-2 calendar-head">
          <button class="text-tt-text inline-flex items-center py-2 px-4 rounded-md hover:bg-gray-50 hover:font-semibold focus:outline-none" tabindex="-1">
  Monday 8
</button>

        </div>
      
        <div class="flex-1 flex justify-center items-end pb-2 calendar-head">
          <button class="text-tt-text inline-flex items-center py-2 px-4 rounded-md hover:bg-gray-50 hover:font-semibold focus:outline-none" tabindex="-1">
  Tuesday 9
</button>

        </div>
      
        <div class="flex-1 flex justify-center items-end pb-2 calendar-head">
          <button class="text-tt-text inline-flex items-center py-2 px-4 rounded-md hover:bg-gray-50 hover:font-semibold focus:outline-none" tabindex="-1">
  Wednesday 10
</button>

        </div>
      
        <div class="flex-1 flex justify-center items-end pb-2 calendar-head">
          <button class="text-tt-text inline-flex items-center py-2 px-4 rounded-md hover:bg-gray-50 hover:font-semibold focus:outline-none" tabindex="-1">
  Thursday 11
</button>

        </div>
      
        <div class="flex-1 flex justify-center items-end pb-2 calendar-head">
          <button class="text-tt-text inline-flex items-center py-2 px-4 rounded-md hover:bg-gray-50 hover:font-semibold focus:outline-none" tabindex="-1">
  Friday 12
</button>

        </div>
      
        <div class="flex-1 flex justify-center items-end pb-2 calendar-head">
          <button class="text-tt-text inline-flex items-center py-2 px-4 rounded-md hover:bg-gray-50 hover:font-semibold focus:outline-none" tabindex="-1">
  Saturday 13
</button>

        </div>
      
        <div class="flex-1 flex justify-center items-end pb-2 calendar-head">
          <button class="text-tt-text inline-flex items-center py-2 px-4 rounded-md hover:bg-gray-50 hover:font-semibold focus:outline-none" tabindex="-1">
  Sunday 14
</button>

        </div>
      
    </div>
  </div>

  <div class="h-full flex-1 flex flex-row relative">  
    <div class="flex flex-col border-r border-tt-border-calendar" style="width: 40px">  
      
        <div id="hour_line_7" class="relative h0">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">7</span>
        </div>
      
        <div id="hour_line_8" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">8</span>
        </div>
      
        <div id="hour_line_9" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">9</span>
        </div>
      
        <div id="hour_line_10" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">10</span>
        </div>
      
        <div id="hour_line_11" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">11</span>
        </div>
      
        <div id="hour_line_12" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">12</span>
        </div>
      
        <div id="hour_line_13" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">13</span>
        </div>
      
        <div id="hour_line_14" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">14</span>
        </div>
      
        <div id="hour_line_15" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">15</span>
        </div>
      
        <div id="hour_line_16" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">16</span>
        </div>
      
        <div id="hour_line_17" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">17</span>
        </div>
      
        <div id="hour_line_18" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">18</span>
        </div>
      
        <div id="hour_line_19" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">19</span>
        </div>
      
        <div id="hour_line_20" class="relative flex-1">
          <span class="absolute right-6 -bottom-2 text-xs text-tt-text-dimmed">20</span>
        </div>
      
    </div>
    <div phx-hook="TimetaskApp.WeekCalendar#WeekCalendar" class="flex-1 flex" id="week-calendar-columns" x-init="fromHour = +$el.dataset.fromHour; toHour = +$el.dataset.toHour;" x-data="week_calendar_data" data-from-hour="7" data-to-hour="20">  
      <div class="w-0 h-full flex flex-col"> 
        
          <div id="hour_7" class="calendar-line flex-1"></div>
        
          <div id="hour_8" class="calendar-line flex-1"></div>
        
          <div id="hour_9" class="calendar-line flex-1"></div>
        
          <div id="hour_10" class="calendar-line flex-1"></div>
        
          <div id="hour_11" class="calendar-line flex-1"></div>
        
          <div id="hour_12" class="calendar-line flex-1"></div>
        
          <div id="hour_13" class="calendar-line flex-1"></div>
        
          <div id="hour_14" class="calendar-line flex-1"></div>
        
          <div id="hour_15" class="calendar-line flex-1"></div>
        
          <div id="hour_16" class="calendar-line flex-1"></div>
        
          <div id="hour_17" class="calendar-line flex-1"></div>
        
          <div id="hour_18" class="calendar-line flex-1"></div>
        
          <div id="hour_19" class="calendar-line flex-1"></div>
        
          <div id="hour_20" class="calendar-line"></div>
        
      </div>
      <div class="flex-1 flex" id="week-calendar-days-container" x-ref="days_container" @mousemove.outside="updateNewTimeboxOutside($event)" @mouseup.stop.outside="stopNewTimebox()" @keydown.escape.window="newTimebox = null"> 
        
          <div id="day_col_2021-11-08" data-date="2021-11-08" class="flex-1 border-r border-tt-border-calendar relative" @mousedown.stop="startNewTimebox($event, $el.dataset.date)" @mousemove.stop="onColumnMouseMouse($event, $el.dataset.date)" " @mouseup.stop="onColumnMouseUp()">
            <div :style="`
                display: ${showNewTimebox(&#39;2021-11-08&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${newTimeboxGeometry().height}px;
                top: ${newTimeboxGeometry().top}px;
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-50"></div> 

            <div :style="`
                display: ${showMovingTimebox(&#39;2021-11-08&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${movingTimeboxGeometry().height}px;
                top: ${movingTimeboxGeometry().top}px;
                ${movingTimeboxColors()};
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-100 z-20"></div> 
            

          </div>
        
          <div id="day_col_2021-11-09" data-date="2021-11-09" class="flex-1 border-r border-tt-border-calendar relative" @mousedown.stop="startNewTimebox($event, $el.dataset.date)" @mousemove.stop="onColumnMouseMouse($event, $el.dataset.date)" " @mouseup.stop="onColumnMouseUp()">
            <div :style="`
                display: ${showNewTimebox(&#39;2021-11-09&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${newTimeboxGeometry().height}px;
                top: ${newTimeboxGeometry().top}px;
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-50"></div> 

            <div :style="`
                display: ${showMovingTimebox(&#39;2021-11-09&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${movingTimeboxGeometry().height}px;
                top: ${movingTimeboxGeometry().top}px;
                ${movingTimeboxColors()};
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-100 z-20"></div> 
            

          </div>
        
          <div id="day_col_2021-11-10" data-date="2021-11-10" class="flex-1 border-r border-tt-border-calendar relative" @mousedown.stop="startNewTimebox($event, $el.dataset.date)" @mousemove.stop="onColumnMouseMouse($event, $el.dataset.date)" " @mouseup.stop="onColumnMouseUp()">
            <div :style="`
                display: ${showNewTimebox(&#39;2021-11-10&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${newTimeboxGeometry().height}px;
                top: ${newTimeboxGeometry().top}px;
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-50"></div> 

            <div :style="`
                display: ${showMovingTimebox(&#39;2021-11-10&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${movingTimeboxGeometry().height}px;
                top: ${movingTimeboxGeometry().top}px;
                ${movingTimeboxColors()};
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-100 z-20"></div> 
            

          </div>
        
          <div id="day_col_2021-11-11" data-date="2021-11-11" class="flex-1 border-r border-tt-border-calendar relative" @mousedown.stop="startNewTimebox($event, $el.dataset.date)" @mousemove.stop="onColumnMouseMouse($event, $el.dataset.date)" " @mouseup.stop="onColumnMouseUp()">
            <div :style="`
                display: ${showNewTimebox(&#39;2021-11-11&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${newTimeboxGeometry().height}px;
                top: ${newTimeboxGeometry().top}px;
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-50"></div> 

            <div :style="`
                display: ${showMovingTimebox(&#39;2021-11-11&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${movingTimeboxGeometry().height}px;
                top: ${movingTimeboxGeometry().top}px;
                ${movingTimeboxColors()};
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-100 z-20"></div> 
            

          </div>
        
          <div id="day_col_2021-11-12" data-date="2021-11-12" class="flex-1 border-r border-tt-border-calendar relative" @mousedown.stop="startNewTimebox($event, $el.dataset.date)" @mousemove.stop="onColumnMouseMouse($event, $el.dataset.date)" " @mouseup.stop="onColumnMouseUp()">
            <div :style="`
                display: ${showNewTimebox(&#39;2021-11-12&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${newTimeboxGeometry().height}px;
                top: ${newTimeboxGeometry().top}px;
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-50"></div> 

            <div :style="`
                display: ${showMovingTimebox(&#39;2021-11-12&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${movingTimeboxGeometry().height}px;
                top: ${movingTimeboxGeometry().top}px;
                ${movingTimeboxColors()};
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-100 z-20"></div> 
            

          </div>
        
          <div id="day_col_2021-11-13" data-date="2021-11-13" class="flex-1 border-r border-tt-border-calendar relative" @mousedown.stop="startNewTimebox($event, $el.dataset.date)" @mousemove.stop="onColumnMouseMouse($event, $el.dataset.date)" " @mouseup.stop="onColumnMouseUp()">
            <div :style="`
                display: ${showNewTimebox(&#39;2021-11-13&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${newTimeboxGeometry().height}px;
                top: ${newTimeboxGeometry().top}px;
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-50"></div> 

            <div :style="`
                display: ${showMovingTimebox(&#39;2021-11-13&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${movingTimeboxGeometry().height}px;
                top: ${movingTimeboxGeometry().top}px;
                ${movingTimeboxColors()};
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-100 z-20"></div> 
            

          </div>
        
          <div id="day_col_2021-11-14" data-date="2021-11-14" class="flex-1 border-r border-tt-border-calendar relative" @mousedown.stop="startNewTimebox($event, $el.dataset.date)" @mousemove.stop="onColumnMouseMouse($event, $el.dataset.date)" " @mouseup.stop="onColumnMouseUp()">
            <div :style="`
                display: ${showNewTimebox(&#39;2021-11-14&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${newTimeboxGeometry().height}px;
                top: ${newTimeboxGeometry().top}px;
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-50"></div> 

            <div :style="`
                display: ${showMovingTimebox(&#39;2021-11-14&#39;) ? &#39;block&#39;: &#39;none&#39;};
                height: ${movingTimeboxGeometry().height}px;
                top: ${movingTimeboxGeometry().top}px;
                ${movingTimeboxColors()};
              `" class="absolute left-3 right-0 rounded-md bg-gray-100 opacity-100 z-20"></div> 
            

          </div>
        
      </div>
    </div>
  </div>
</div>

  </div>

  


  


    <div x-data>
  
    
  
    
  
</div>



    </div>
  <iframe hidden height="0" width="0" src="/phoenix/live_reload/frame"></iframe></body>
</html>
</div>

What you are asking is inside the element with id week-calendar-days-container

cmo

cmo

Probably doesn’t matter but you have a random " in the divs with the IDs <div id="day_col_2021-11-09"?

I’ve had to use alpines template tag (wrapped in a Raw tag - I use surface) for somewhere where I generated a list of things which had myriad alpine bindings. Unfortunately, I’ve stepped away from the computer for the day so I can’t show you an example.

fceruti

fceruti OP

By any chance are you back yet? I’m stilll having this issue

cmo

cmo

Here is a cut down version. Note that I’m using Surface, hence the <#Raw> tags (I assume there is a parallel in plain old liveview) and different syntax. The hook reads attributes from the hidden spans and sends them to Apline. Alpine creates the html for the options. I had a bit of trouble getting this to work and when it worked I stopped touching it and moved on. I hope to revist if/when I get some time :wink:

    <div
      id={"column-filter-#{@field}"}
      :hook="ColumnOptionsFilter"
      x-data="{
        ...
        options: [],
        ...
      }"
      @options-loaded="options = $event.detail.options"
    ...
    >
      <div id={"column-filter-#{@field}-data"} hidden>
        {#for option <- @all_options}
          <span data-option={option} />
        {/for}
      </div>

    ...

        <div id={"column-filter-options-#{@field}"} phx-update="ignore">
          <#Raw>
          <template x-for="(option, index) in options" :key="index">
          </#Raw>
            <div class="flex items-center py-1">
              <input
                x-model="selected"
                :value="option"
                :id="option"
                :name="option"
                type="checkbox"
                :class="{ 'opacity-50': !available[index]}"
                class="h-4 w-4 text-blue-900 focus:ring-blue-900 border-gray-300"
              />
              <label
                :for="option"
                x-text="option"
                :class="{ 'text-gray-400': !available[index], 'text-gray-900': available[index] }"
                class="ml-2 block text-sm"
              />
            </div>
          <#Raw>
          </template>
          </#Raw>
        </div>
     ...
     </div>

Hook:

const ColumnOptionsFilter = {
  mounted() {
    const options = Array.from(
      document.getElementById(this.el.id + "-data").children || []
    ).map(({ dataset: { option, available, selected } }) => {
      return option === undefined ? "[Blanks]" : option;
    });

   ...

    setTimeout(() => {
      if (options.length > 0) {
        var event = new CustomEvent("options-loaded", {
          detail: { options: options, available: available },
        });
        this.el.dispatchEvent(event);
        this.optionsLoaded = true;
      }
    }, 0);
  },
fceruti

fceruti OP

:raised_hands: thanks!

Me too!

Where Next? Top

Trending in Questions Top

water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Alvinkariuki
How Can I Optimise Compile Time Dependencies I have been building an elixir application for about 2 years now. Many modules and files ha...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New

Other Trending Topics Top

budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
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
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews