# Vue 2 + TypeScript + Vite https://www.mathew-paul.nz/posts/how-to-use-vue2-with-vite/ ## Uruchamianie (dev) `npm run dev` ## Konfiguracja w trybie dev dane, external ale również schema musimy podać w routerze, zeminiony został formMixin który przepisuje schemę w odpowiednie miejsce ```JS props: { datamodel: offerModel, schema: [wzorSchema], external, }, ``` ## Definiowanie schematów - Folder `./src/schema`; - Schemat z zasady musi być zdefiniowany w jednym pliku, można części schematów współdzielić w wydzielonym subfolderze (np. `./src/schema/shared`) - Przy definowaniu schematów dobrze podać typ `$root` i `$external` do funkcji `predefineSchema` ```TypeScript const def = predefineSchema(); ``` - enumy MUSZA być zdefiniowane w tym samym pliku co schemat, inaczej jest problem z kompilacją: ```TypeScript enum TypyEwidencji { KRS = 1, INNY = 2 } export const oferentSchema = def({ type: 'object', properties: { TypEwidencji: { type: 'number' as EnumType, }, NumerKrs: { disabled() { return this.TypEwidencji === TypyEwidencji.INNY || !this.TypEwidencji; } } }) ``` - schemat MUSI (ze względu na kompilacje) stanowić domyślny export ```TypeScript export default wzorSchema; ``` - ZABRONIONE jest stosowanie: - `$ref` i `allOf` - schemay łaczy się funkcją do definiowania schematu lub klasycznie przez spread - `aggreagate` - należy zastąpić przez `calc()` i funkcje agregujące z `this.$methods` np: ```TypeScript calc() { return this.$methods.sum(this.$root.Kosztorys, 'Dotacja'); } ``` zagnieżdzone sumowanie ```TypeScript calc() { return this.$methods.sum(this.$root.Kosztorys, x => this.$methods.sum(x.Lata,y => y.Netto)); } ``` - `this.$obj.$parent` może być null, wieć TypeScript zaproponuje `this.$obj.$parent?` ale jeśli jedeśmy pewni to lepiej zapisać `this.$obj.$parent!`, ładniej się skompiluje ### Strategia tworzenia schematów i ich konwersji z .json 1. Stworzyć plik `{NazwaSchematu}.ts` 2. Z pakietu `@witkac/jschema` zaimportować `predefineSchema` 3. Na razie bez typowania: ```TypeScript const def = predefineSchema(); ``` 4. Skopiować zawartość json i wstawić w miejsce `...` ```TypeScript const wzorSchema = def(...) ``` 5. Pozbyć się wszelkich `$ref` i `allOf`, to jest niezbędne aby dobrze działało typowanie - wydzielić `definition` do którego kieruje `$ref` do osobnego schematu: ```TypeScript const adresSchema = def(...) ``` - łaczenie, które odbywało sie przez `allOf` zostąpić przeciązaniem schematów obsługiwanym przez `def`, przeciążamy WYŁACZNIE na poziomie obiektu ```TypeScript AdresKorespondencyjny: def(adresSchema,{ title: "Adres korespondencyjny" }) ``` 6. Już powinno działać prawidłowo, natomiast jeśli chcemy mieć fajne typowanie to należy wykonać kolejne kroki 7. Zadbać żeby każdy element typu `object` był otoczony `def`: - przed ```TypeScript Oferenci: { type: 'array', default: [], items: { type: 'object', properties: {...} } } ``` - po ```TypeScript Oferenci: { type: 'array', default: [], items: def({ type: 'object', properties: {...} }) } ``` 8. wszystkie wyliczalne właściwości (jak `calc`) zamienić na funkcje, (UWAGA: NIE WOLNO stosować funkcji lambda czyli np. `calc: () => this.Ilosc`) - przed ```TypeScript "calc": "this.Ilosc * this.KosztJednostkowy" ``` - po ```TypeScript calc() { return this.Ilosc * this.KosztJednostkowy } ``` 9. Użycie `$methods` (ale też np. `$obj` czy `$root`) wymaga przedrostka `this.` - przed ```TypeScript "calc": "$obj.$parent.$key" ``` - po ```TypeScript calc() { return this.$obj.$parent!.$key; } ``` 10. Aby odpowiednio typować `this.$root` i `this.$external` należy w `predefineSchema` podać albo typy, albo wartości ```TypeScript import type { External } from '../data/external'; import type { OfferModel } from '../data/model'; const def = predefineSchema(); ``` ```TypeScript import { external } from '../data/external'; import { offerModel } from '../data/model'; const def = predefineSchema(offerModel,external); ``` 11. Własne metody dostępne w formularzu najlepiej zdefiniować jako obiekt: ```TypeScript const myMethods = { add(a: int,b: int): int { return a + b } } ``` i wtedy dodać do głównego schematu: ```TypeScript const wzorSchema = def({ $methods: myMethods }) ``` Aby uzyskać typowany dostęp do tych metod w funkcjach schematu, należy podać ten obiekt do `predefineSchema`: ```TypeScript const def = predefineSchema(); // lub const def = predefineSchema(offerModel,external,myMethods); ``` ## Definiowanie formularzy - Folder `./src/views` - Subkomponenty nalezy umieścić w innym folderze - Typowanie jest zrealizowane poprzez typowanie `foromMixin` i typ `FormMixinType` ```TypeScript // import samego formMixin import { formMixin } from '@witkac/smartadmin-components'; // import typowania (musi być osobno, bo to trochę kombinowany typ) import type { FormMixinType, SectionType } from '@witkac/smartadmin-components/src/typings'; // typowanie z Vue 2.7 import { defineComponent } from 'vue'; // typ danych $external import type { External } from '../data/external'; // typ schematu import type { WzorSchema } from '../schema/WzorSchema'; export default defineComponent({ mixins: [formMixin as FormMixinType], ... }) ``` - Dzięki temu typowane na template są zmienne `$schema` `$external` i `model` - Funkcje/computed z `formMixin` i `schemaMixin` również są typowane (np. `prevStep()`) ## Kompilowanie - skrypt kompilujący jest umieszczony w źródłach `smartadmin-components` - kompilowane są wszystkie schematy (pliki `.ts` z folderu `./src/schema`) i tworzone są pliki `.json` i `.js`, czyste bez żadanych `defineSchema`, enumy kompilowane są do liczb, a funkcje kompilowane do tekstów lub tablic - kompilowane są wszystkie widoki (pliki `.vue` z folderu `./src/views`) - jesli w widoku zdefiniowana jest zmienna `sections` to jest ona zamieniana na JSON i zapisywana w pliku `{ViewName}Sections.json` - sam widok jest kompilowany do funkcji formularza zgodnej z tym co jest aktualnie w witkacu