Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lingering series in line chart after option.series update #13

Closed
pablosettecase opened this issue Jan 15, 2025 · 2 comments
Closed

lingering series in line chart after option.series update #13

pablosettecase opened this issue Jan 15, 2025 · 2 comments
Labels
question Further information is requested

Comments

@pablosettecase
Copy link

I'm using line charts with the x-axis of type "time" and each series with type "line". I fetch new data and update the option.series, which works fine with a single series. I'm not able to update the series correctly with multiple series. There is always one old/previous series that lingers and is still rendered on the page.

Basically, there is a date picker, a few toggles, and data fields that the user can select from a long list. The user can select multiple, and 3 fields are selected by default. On mount, data is fetched and the chart is plotted correctly. However, upon selecting other fields, or de-selecting fields in the UI, new data is fetched, and the plot is redrawn with the new data as expected, but one old series is still plotted, even though that series is removed from option.series and from my state.data ref.

My issue and question is whether I am updating the option.series correctly after my data fetches.

<template>

  <UCard>
    <template #header>
      <div class="flex justify-center mx-auto p-5 space-x-2">
        <div class="flex-initial w-72">
          <VueDatePicker v-if="isDark" dark range v-model="date" :model-value="date" @update:model-value="getData" model-type="yyyy-MM-dd" :enable-time-picker="false" utc position="left" class="" />
          <VueDatePicker v-else             range v-model="date" :model-value="date" @update:model-value="getData" model-type="yyyy-MM-dd" :enable-time-picker="false" utc position="left" class="" />
        </div>
        <div class="flex-initial max-w-48">
          <input v-model="yAxisMin" type="number" id="yAxisMin" class="block w-20 h-9 p-1  mb-1 border dark:bg-zinc-800 dark:border-zinc-700 border-gray-300 rounded-lg" placeholder="" required />
          <label for="yAxisMin" class="block ml-2 mb-2 text-sm font-medium">Y-Axis Min</label>
        </div>
        <div class="flex-initial max-w-48">
          <input v-model="yAxisMax" type="number" id="yAxisMax" class="block w-20 h-9 p-1  mb-1 border dark:bg-zinc-800 dark:border-zinc-700 border-gray-300 rounded-lg" placeholder="" required />
          <label for="yAxisMax" class="block ml-2 mb-2 text-sm font-medium">Y-Axis Max</label>
        </div>
        <div class="flex-initial w-24">
          <div class="py-2">
            <UToggle @change="autoAxisToggle" class="ml-6" v-model="autoAxis" />
          </div>
          <label for="autoAxis" class="block ms-2 text-sm font-medium">Auto Y-Axis</label>
        </div>
        <div class="flex-initial w-24">
          <div class="py-2">
            <UToggle class="ml-6" v-model="showDataLabelsToggle" />
          </div>
          <label for="showDataLabelsToggle" class="block ms-2 text-sm font-medium">Data Labels</label>
        </div>
        <div class="flex-initial w-24">
          <USelectMenu class="h-10" @change="getData" v-model="selectedSvn" :options="svnList"/>
          <label for="autoAxis" class="block ms-2 text-sm font-medium">SVN</label>
        </div>
        <div class="flex-initial w-52">
          <USelectMenu class="h-10" @change="getData" v-model="selectedFields" :options="fieldsListOrbClockSol" multiple />
          <label for="autoAxis" class="block ms-2 text-sm font-medium">Fields</label>
        </div>
      </div>
    </template>

    <VChart ref="chart" class="chart" :option="option" :loading="state.loading"/>
  </UCard>
  
</template>

<script setup>
  import VueDatePicker from '@vuepic/vue-datepicker';
  import '@vuepic/vue-datepicker/dist/main.css'
  import { ref } from 'vue';
  import { fieldsListOrbClockSol } from '@/assets/fieldsListOrbClockSol.js'
  const runtimeConfig = useRuntimeConfig()
  const yAxisMinDefault = 'dataMin'
  const yAxisMaxDefault = 'dataMax'
  const yAxisMin = ref(yAxisMinDefault)
  const yAxisMax = ref(yAxisMaxDefault)
  const autoAxis = ref(true)
  const showDataLabelsToggle = ref(false)
  const date = ref()
  const isLoading = ref(false)
  const chart = useTemplateRef('chart')
  const state = reactive({
    data: [],
    loading: true,
  });
  const toast = useToast()
  const colorMode = useColorMode()
  const isDark = computed({
    get () {
      return colorMode.value === 'dark'
    }
  })
  const selectedFields = ref([])
  const selectedString = computed(() => {
    return selectedFields.value.map((fieldsListOrbClockSol) => fieldsListOrbClockSol.label).join(", ")
  })
  const svnList = ref()
  const selectedSvn = ref({prn: '28', value: '78', label: '78'})

  const autoAxisToggle = function() {
    if (autoAxis.value) {
      yAxisMin.value = null
      yAxisMax.value = null
    } else {
      yAxisMin.value = yAxisMinDefault
      yAxisMax.value = yAxisMaxDefault
    }
  }

  onMounted(() => {
    const endDate = new Date();
    const startDate = new Date(new Date().setDate(endDate.getDate() - 1));
    date.value = [startDate.toISOString(), endDate.toISOString()];
    selectedFields.value = [fieldsListOrbClockSol[8], fieldsListOrbClockSol[10], fieldsListOrbClockSol[12]]
    getSvnlist();
    getData();
  });

  const getSvnlist = async function () {
    state.loading = true

    const base_url = 'http://localhost:8000';
    const endpoint = '/api/v1/svn/map'
    const url = `${base_url}${endpoint}`
    console.log(`front end API call to ${url}`)
    const start = date.value[0]
    const end   = date.value[1]
    console.log(`start: ${start}`)
    console.log(`end  : ${end}`)
    const options = {
      query: {
        'startDate': start,
        'endDate':   end,
        'constellation': 'gps'
      }
    }
    $fetch(url, options )
    .then((data) => {
      const d1 = data.data
      svnList.value = d1
      const x = 1
    }).catch((e) => {
      const msg = `Error fetching SVN map for ${date.value}`
      console.error(msg, e);
      toast.add({
        title: 'Data Fetch Error',
        description: 'There was an error fetching SVN data. Please try again momentarily.',
      });
    })
  }

  const option = ref({
    title: {
      text: 'Orbit and Clock Solutions - JPL and NGA',
      left: 'center',
      subtext: selectedString
    },
    useUTC: true,
    darkMode: isDark,
    toolbox: {
      feature: {
        dataZoom: {
          yAxisIndex: 'none'
        },
        saveAsImage: {},
        dataView: { show: true }
      }
    },
    tooltip: {
      trigger: 'axis'
    },
    xAxis: {
      type: 'time',
      splitLine: {
        show: false
      },
      axisLabel: {
        formatter: '{yyyy}-{MM}-{dd}'
      }
    },
    yAxis: {
      type: 'value',
      offset: 30,
      name: '',
      nameLocation: 'middle',
      nameTextStyle: {
        lineHeight: '56'
      },
      boundaryGap: [0, '100%'],
      splitLine: {
        show: false
      },
      min: yAxisMin,
      max: yAxisMax
    },
    series: state.data
  })

  const getData = async function () {
    state.loading = true
    // option.value.series = []
    const base_url = 'http://localhost:8000';
    const endpoint = '/api/v1/sol/orb'
    const url = `${base_url}${endpoint}`
    const start = date.value[0]
    const end   = date.value[1]
    var selectedFieldsString = ''
    let count = 0
    selectedFields.value.forEach(element => {
      selectedFieldsString += element.fieldName + ','
      console.log(`${count}) element.label: ${element.label}, element.fieldName: ${element.fieldName}`)
      count += 1
    })
    selectedFieldsString = selectedFieldsString.substring(0,selectedFieldsString.length-1)
    const svn2 = selectedSvn.value.value
    console.log(`front end API call to ${url}`)
    console.log(`start : ${start}`)
    console.log(`end   : ${end}`)
    console.log(`svn   : ${svn2}`)
    console.log(`fields: ${selectedFieldsString}`)
    const options = {
      query: {
        'startDate': start,
        'endDate':   end,
        'svn':       svn2,
        'constellation': 'gps',
        'metrics': selectedFieldsString
      }
    }
    $fetch(url, options )
    .then((data) => {
      state.data = []
      // option.value.series = []
      const allSeries = []
      selectedFields.value.forEach(element => {
        console.log(`element.label: ${element.label}, element.fieldName: ${element.fieldName}`)
        const d = data[element.fieldName]
        const series = {
          name: element.fieldName, 
          data: d, 
          type: 'line',
          label: {
            show: showDataLabelsToggle.value
          }
        }
        // state.data.push(series)
        // option.value.series.push(series)
        allSeries.push(series)
      });
      chart.value?.setOption({ series: allSeries })
      // option.value.series = state.data
      // option.series = allSeries
      state.loading = false;
    }).catch((e) => {
      state.loading = false;
      console.log(e);
      const msg = `Error fetching URET daily data for ${date.value}`
      console.log(msg);
      toast.add({
        title: 'Data Fetch Error',
        description: 'There was an error fetching data. Please try again momentarily.',
      });
    })
  }

</script>

<style scoped>
.chart {
  height: 600px;
}
</style>
@kingyue737 kingyue737 added the question Further information is requested label Jan 16, 2025
@kingyue737
Copy link
Owner

Matthias Mertens post a well-explained answer here:

https://stackoverflow.com/questions/79356331/how-to-update-series-data-correctly-in-nuxt-echarts-module/79357374#79357374

Please let me know if this still cannot solve your issue

@pablosettecase
Copy link
Author

Yes! Solved with that StackOverflow answer. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants