Vue3 + Django i implementacja Google Maps

0

Hej
Mam projekt django + vue (do nauki). Próbuję zaimplementować mapy google. Zainstalowałem na backendzie-> django-location-field i na frontendzie Google Vue 3.

Dane wyjściowe z django-location-field wyglądają tak --> 51.39772199999999,16.2095788, a mapy Google Vue 3 wymagają wprowadzenia takiego formatu {lat: 51.093048, lng: 6.842120},
Wiem że muszę użyć opcji split na danych wejściowych z backendu przez axios.

Próbowałem coś takiego :

computed: {
    preparedAvaFac() {
        return this.lok.map(row => {
             const rowObj = row.split(",");
             return {
                 val1: row[0], 
                 val2: row[1],
             }
        }
        )
    },

ale rzuca błędem Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'map')

Tutaj cały kod z views/FirmaDetails.vue

<template>
<section class="portfolio-block projects-cards">
    <div class="container">
        <div class="heading">
            <h2>{{ firma.nazwa_firmy }}</h2>
        </div>
        <div class="row">
            <p>{{ firma.opis }}</p>
            <p>{{ firma.strona_www}}</p>
            <p>{{ firma.miasto}}</p>
            <GoogleMap api-key="Mój APi KEJ" style="width: 100%; height: 500px" :center="center" :zoom="15">
                <Marker :options="{ position: center }" />
            </GoogleMap>
                {{val1}}

            <p>{{ firma.lokalizacja}}</p>
        </div>
    </div>
</section>
</template>

<script>
import axios from 'axios'
import { GoogleMap, Marker } from "vue3-google-map";

export default {
    
    name: 'FirmaDetails',
        setup() {
            
      // Get toast interface
      // const toast = useToast();
      // return { toast }
    },
    data() {
        return {
            firma: [],
            errors: [],
            lok: [],
            val1: [],
            val2: [],
        }
    },
    components: { GoogleMap, Marker },

    props: {
        uuid: {
            type: String,
            required: true,
      
    },
    },

    mounted() {
        this.getItemsProfiles()
    },

computed: {
    preparedAvaFac() {
        return this.lok.map(row => {
             const rowObj = row.split(",");
             return {
                 val1: row[0], 
                 val2: row[1],
             }
        }
        )
    },

    methods: {
        async getItemsProfiles() {

            this.$store.commit('setIsLoading', true)

            axios
                .get(`/api/v1/firma/${this.uuid}/`)
                .then(response => {
                     this.firma = response.data
                     this.lok = response.data.lokalizacja
                     console.log(this.firma)
                     

                })

                
                .catch(error => {
                    console.log(error)
                  
                })

                this.$store.commit('setIsLoading', false)


            
        }
    }
}
}
</script>

Przyznam że JS mało znam i dlatego pytam jak zrobić split na danych wejściowych i przypisać do zmiennych?

0

Czym jest to this.lok?

Bo ogólnie, żeby zamienić string 51.39772199999999,16.2095788 na obiekt to wystarczy coś takiego

const [lat, lng] = '51.39772199999999,16.2095788'.split(',');
const pos = { lat, lng };

console.dir(pos) // { lat: '51.39772199999999', lng: '16.2095788' }

EDIT:

W tym miejscu tworzysz zmienną rowObj i później jej nie używasz

return this.lok.map(row => {
   const rowObj = row.split(",");
   
   return {
       val1: row[0], // tutaj pewnie powinno być rowObj[0]
       val2: row[1], // a tutaj rowObj[1]
   }
}
0

Ups sorry już poprawiłem this.lok wyciąga z firmy lokalizację i ją przechowuje w lok
Próbowałem coś takiego lecz " {lat: '', lng: undefined}"

computed: {
    preparedAvaFac() {
                const [lat, lng] = this.lok.toString().split(',');
                const pos = { lat, lng };

                console.log(pos)
                return pos
    },
},
0

W takim razie... przy tworzeniu komponentu przypisujesz zmiennej lok tablice i musisz zmienić to na string

 data() {
    return {
        firma: [],
        errors: [],
        lok: '',
        val1: [],
        val2: [],
    }
},

{lat: undefined, lng: undefined} możesz dostawać jeśli wywołujesz najpierw preparedAvaFac przed pobraniem danych i przypisaniem lokalizacji z backendu.

Musisz najpierw pobrać dane z backendu i dopiero później wywołać preparedAvaFac tak jak pokazałem w pierwszym poście

0

i pojawia się błąd "FirmaDetails.vue?66b1:66 Uncaught (in promise) TypeError: this.lok.map is not a function" muszę koniecznie zacząć naukę JS bo podstawy mnie przygniatają

    mounted() {
        this.getItemsProfiles()
        this.preparedAvaFac()
    },

    methods: {

    preparedAvaFac() {
        return this.lok.map(row => {
             const rowObj = row.toString().split(",");
             return {
                 val1: rowObj[0], 
                 val2: rowObj[1],
             }
        })
    }, 
1

Ja chyba coś źle zrozumiałem.

Wydawało mi się, że pobierasz z API i przypisujesz do lok zmienną typu string, a metoda map jest do tablic.

Jeśli faktycznie jest to string to wystarczy taki fragment

preparedAvaFac() {
  const [lat, lng] = this.lok.split(',');

  return { lat, lng };
}

Musisz tą metodę wywoływać po pobraniu danych z backendu, bo na samym początku będzie zwracać {lat: undefined, lng: undefined}, ponieważ początkowo w Twoim komponencie jest pusty string (chodzi mi o zmienną lok).

Więc proponowałbym w htmlu sprawdzać długość zmiennej this.lok

<div v-if="lok.length">
   <GoogleMap ...></GoogleMap>
</div>

Jeśli v-if okaże sie prawdą to mamy już dane z backendu i możemy wywołać metodę preparedAvaFac

https://vuejs.org/guide/essentials/conditional.html

0

Dobra mam coś takiego

        axios
                .get(`/api/v1/firma/${this.uuid}/`)
                .then(response => {
                     this.firma = response.data
                     this.lok = response.data.lokalizacja
                     console.log(this.firma)
                     const [lat, lng] = this.lok.split(',');
                     console.log(lat, lng);
                     this.center = {lat: lat, lng: lng};
                     this.center.replaceAll('"', '');
                })

Output z tego jest taki { "lat": "51.39772199999999", "lng": "16.2095788" } a potrzebuję taki {lat: 51.39772199999999, lng: 16.2095788} czyli usunąć cudzysłowie. Jakiś pomysł? replaceAll nie chce działać

1

zwracasz stringa z backendu zamiast floata (poczytaj o rodzajach typu danych - podstawa), więc albo z backendu zwrócisz odpowiedni typ danych albo wykorzystaj parseFloat() na froncie mniej więcej tak jak poniżej:

this.center = {lat: parseFloat(lat), lng: parseFloat(lng)};

i zacznij się uczyć JS, bo tylko sobie krzywdę robisz, albo odstaw front jak nie chcesz, albo naucz się korzystać z przeglądarki Google - to też dość ważne xd

0

Dzięki wszystkim za pomoc :) wszystko działa.
Co do ostatniej wypowiedzi - zwracam stringa z backendu ponieważ tak jest w django-location-field, dopiero się uczę django i rest frameworka i pomyślałem że szarpnę się przy okazji na frontend w vue aby mieć satysfakcję z tego że coś fajnie działa. Przyznam że JS w ogóle się nie uczyłem i wiem że to widać :) Jeszcze raz dzięki

1 użytkowników online, w tym zalogowanych: 0, gości: 1