Time range controls

The ComponentContext instance offers properties and methods that let the UI Component take control of the active time range on a page.

Example

The example below shows how you can read and listen for updates on the time range and how you can set a new time-range. The luxon library is used for formatting dates for the time zone that is provided by the component context's appData object.

<template>
  <main>
    <input type="datetime-local" v-model="from" />
    <input type="datetime-local" v-model="to" />
    <button @click="update" :disabled="isDisabled">Update</button>
  </main>
</template>

<script>
import { DateTime } from 'luxon';

export default {
  name: 'time-range',
  props: ['context'],
  data() {
    return { from: null, to: null };
  },
  computed: {
    isDisabled() {
      // A page can be configured as such that the time range cannot be changed.
      if (!this.context.timeRangeIsAdjustable) {
        return true;
      }

      // Don't allow updates when any input model is empty.
      return !this.from || !this.to;
    }
  },
  created() {
    // Initializes the input models with the current time range values.
    this.from = this.formatValue(this.context.timeRange.from);
    this.to = this.formatValue(this.context.timeRange.to);

    // Listens for changes to the time range and updates the input models.
    this.context.ontimerangechange = newTimeRange => {
      this.from = this.formatValue(newTimeRange.from);
      this.to = this.formatValue(newTimeRange.to);
    };
  },
  methods: {
    formatValue(milliseconds) {
      return DateTime.fromMillis(milliseconds)
        .setZone(this.context.appData.timeZone)
        .toFormat("yyyy-MM-dd'T'T");
    },
    update() {
      const zone = this.context.appData.timeZone;
      this.context.setTimeRange({
        from: DateTime.fromISO(this.from, { zone }).toMillis(),
        to: DateTime.fromISO(this.to, { zone }).toMillis(),
      });
    }
  }
};
</script>

<style scoped>
main {
  display: flex;
  flex-direction: column;
  padding: 1em;
}

input {
  margin-bottom: 1em;
}
</style>
<script>
  import { DateTime } from 'luxon';
  import { onMount } from 'svelte';

  export let context;
  let from = null;
  let to = null;
  $: isDisabled = _isDisabled(from, to);
  
  onMount(() => {
    // Initializes the input models with the current time range values.
    from = _formatValue(context.timeRange.from);
    to = _formatValue(context.timeRange.to);
    
    // Listens for changes to the time range and updates the input models.
    context.ontimerangechange = newTimeRange => {
      from = _formatValue(newTimeRange.from);
      to = _formatValue(newTimeRange.to);
    };
  });
  
  function _formatValue(milliseconds) {
    return DateTime.fromMillis(milliseconds)
      .setZone(context.appData.timeZone)
      .toFormat("yyyy-MM-dd'T'T");
  }
  
  function _isDisabled(from, to) {
    // A page can be configured as such that the time range cannot be changed.
    if (!context?.timeRangeIsAdjustable) {
      return true;
    }

    // Don't allow updates when any input model is empty.
    return !from || !to;
  }
  
  function update() {
    const zone = context.appData.timeZone;
    context.setTimeRange({
      from: DateTime.fromISO(from, { zone }).toMillis(),
      to: DateTime.fromISO(to, { zone }).toMillis(),
    });
  }
</script>

<main>
  <input type="datetime-local" bind:value={from} />
  <input type="datetime-local" bind:value={to} />
  <button on:click={update} disabled={isDisabled}>Update</button>
</main>

<style>
  main {
    display: flex;
    flex-direction: column;
    padding: 1em;
  }

  input {
    margin-bottom: 1em;
  }
</style>