Web Application Development with Quasar Framework
In this tutorial, You can see a rough development process with Quasar Framework which is known as front-end framework with VueJS components.
- Frontend : Quasar (based on Vue.js)
- Backend : Google firebase
- Result
* Web Page : https://checkin.wonyong.net
* Play Store : https://play.google.com/store/apps/details?id=org.kopochecker.app
- Youtube (Korean) : https://www.youtube.com/watch?v=HEttw-RSXxg&list=PLlWoe5hcgrk4qQVIBxDA3d-5ZRfYuITxb
1. Dept. of Smart Finance, Korea Polytechnics Seoul Kangseo Campus
ApplicationDevelopmentw/
QuasarFramework
Basic Course
2. QuasarCLIInstallation
• Prerequisite
Node >=12.22.1 and NPM >=6.14.12
• recommendation node version : v14.17.5
check your node and npm : node -v
npm -v
• npm install -g @quasar/cli
Do not use uneven versions of Node i.e. 13, 15, etc. These versions are not tested with Quasar and often cause issues due to their experimental nature. We highly recommend always using the LTS version of Node.
Ref : https://quasar.dev/quasar-cli/installation
3. HelloworldⅠ(1/2)
• we create a project folder with Quasar CLI
• quasar create <folder_name>
Ref : https://quasar.dev/quasar-cli/installation
(base) waynehwang@wayneui-MacBookPro temp % quasar create hello
___
/ _ _ _ __ _ ___ __ _ _ __
| | | | | | |/ _` / __|/ _` | '__|
| |_| | |_| | (_| __ (_| | |
_____,_|__,_|___/__,_|_|
? Project name (internal usage for dev) hello
? Project product name (must start with letter if building mobile apps) hello
? Project description hello world
? Author wayne hwang <wonyong@wonyong.net>
? Pick your CSS preprocessor: SCSS
? Check the features needed for your project: ESLint (recommended), Vuex, Axios
? Pick an ESLint preset: Prettier
? Continue to install project dependencies after the project has been created? (
recommended) NPM
Quasar CLI · Generated "hello".
[*] Installing project dependencies …
[*] Quasar Project initialization finished!
To get started:
cd hello
quasar dev
4. Helloworld Ⅰ(2/2)
• Look into package.json, App.vue, routes.js, Index.vue, EssentialLink.vue, …
• Run your app with below command:
quasar dev
5. HelloWorldⅡ
• Repository address :
https://github.com/wonyongHwang/kopoPro
fi
le
• git clone https://github.com/wonyongHwang/kopoPro
fi
le
• npm install
• quasar dev
kopoProfile
6. HelloWorldⅡ
• In this practice, we don’t have a
drawer and a footer either. So, only
<q-header> is being a
ff
ected by
<q-layout>.
•
layout
<q-layout view="lHh lpr lFf">
reference : https://quasar.dev/layout/layout#understanding-the-view-prop
7. HelloWorldⅡ
• quasar can detect platform : $q.platfrom.is.~~
eg> if you will deploy app to mobile device(android,
ios) app can detect platform using $q.platform.is.
cordova
$q.platform
<div v-bind:class="{'main': $q.platform.is.desktop, 'mobile_main': $q.platform.is.ipad || $q.platform.is.mobile}"
class="full-height" style="background-color:rgba(0, 0, 0, 0.7);">
reference : https://quasar.dev/options/platform-detection#introduction
14. homework
• check url
• if you have a own domain, netlify allow you to access your web site
• ‘https(let’s encrypt)’ supports both custom domain and netlify domain
21. pagelink
• vue syntax for page link :
<router-link to=“/address”> ~~ </router-link>
<router-link to="/signup" >
<center>New User? Click Here to Register.</center>
</router-link>
22. Homework
• Place and Organize Input Text
fi
elds (E-mail, Password, etc …)
: center alignment
• Password should be masked while typing
• Place Sign-In / Sign-Up buttons
complete your sign-in / sign-up pages!
23. f
irebase
• https://
fi
rebase.google.com/?hl=ko
create a project
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const
fi
rebaseCon
fi
g = {
apiKey: "AIzaSyA~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
authDomain: "kopologinchecker.
fi
rebaseapp.com",
projectId: "kopologinchecker",
storageBucket: "kopologinchecker.appspot.com",
messagingSenderId: "17~~~~~~~~~~~~",
appId: "1:17~~~~~~~~:web:d4~~~~~~~~",
measurementId: “G-H0~~~~~~~~~~~~"
};
24. • npm install --save
fi
rebase
• quasar new boot
fi
rebase
->
fi
rebase.js will be generated in src/boot
-> paste
fi
rebase con
fi
guration to
fi
rebase.js
f
irebase
setting config.
ref : https://quasar.dev/quasar-cli/boot-
fi
les
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/analytics'
const firebaseConfig = {
apiKey: "~",
authDomain: "kopologinchecker.firebaseapp.com",
projectId: "kopologinchecker",
storageBucket: "kopologinchecker.appspot.com",
messagingSenderId: “~",
appId: "~",
measurementId: "~"
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
firebase.analytics();
export const auth = firebase.auth();
28. homework
• implement a sign-up function using
fi
rebase api
• validation logic should be implemented
ex> email/password should not be empty
password should be equal to ‘repeat password’
password must be at least 6 characters long
hint> https://levelup.gitconnected.com/
fi
rebase-auth-management-in-vue-js-with-vuex-9c4a5d9cedc
• move page after sign-up
hint> this.$router.push({ path: 'home' })
import { useRouter, useRoute } from 'vue-router'
export default
{
setup()
{
const router = useRouter()
const route = useRoute()
// Now you can access params like
:
console.log(route.params.id)
;
route.push({path: ‘home’}
)
}
};
vue v3
https://next.router.vuejs.org/guide/advanced/composition-api.html#accessing-the-router-and-current-route-inside-setup
30. management
f
irebaseauthw/vuex
• state management pattern and its library
• state : data
• mutations : change state (sync)
• actions : commit mutation (async)
what vuex is
Actions
State
View
Mutations
this.$store.commit
emit, props
Unidirectional
fl
ow
31. management
f
irebaseauthw/vuex
• state =
fi
re auth info
• ‘
fi
re auth info’ can acquire when we call
signInWithEmailAndPassword()
createUserWithEmailAndPassword()
and so on.
state
Actions
State
View
Mutations
this.$store.commit
import {auth} from "src/boot/firebase"
export default store(function (/* { ssrContext } */) {
const Store = createStore({
modules: {
// example
},
state: {
fireUser:null
},
…
State
32. management
f
irebaseauthw/vuex
• get the current sign-in user is by setting an observer on the Auth object
https://
fi
rebase.google.com/docs/auth/web/manage-users
• state should be null when user signed out
https://
fi
rebase.google.com/docs/auth/web/password-auth?hl=ko
action
actions: {
signOutAction({commit}) {
auth.signOut()
.then(() => {
commit("setFireUser", null);
})
},
authAction({ commit }) {
auth.onAuthStateChanged(user => {
if (user) {
commit("setFireUser", user);
}
});
},
},
mutations: {
setFireUser(state, firebaseUser){
state.fireUser = firebaseUser
}
Actions
Mutations
35. management
f
irebaseauthw/vuex
• commit state when my application obtain a
fi
rebase auth
• get a
fi
rebase auth to display user info
• check a
fi
rebase auth
usage example
auth.signInWithEmailAndPassword(this.text, this.password).then(
(userCredential) => {
this.$store.commit("setFireUser", userCredential.user);
}
)
<div class="text-h6" align="center">
Hi, {{ this.name }}({{ getFireUser.email }})
<br>
…
computed: {
...mapGetters(["getFireUser", "isUserAuth"])
},
mounted() {
this.authAction();
…
methods: {
...mapActions(["signOutAction","authAction"]),
import { useStore } from "vuex"
;
export default
{
setup()
{
const store = useStore()
;
store.commit("setFireUser", userCredential.user)
;
}
};
vue v3
https://kyounghwan01.github.io/blog/Vue/vue3/composition-api-vuex/#vuex-%E1%84%89%E1%85%A6%E1%84%90%E1%85%B5%E1%86%BC-%E1%84%86%E1%85%B5%E1%86%BE-store-module-1%E1%84%80%E1%85%A2%E1%84%85%E1%85%A9-%E1%84%89%E1%85%B5%E1%86%AF%E1%84%92%E1%85%A2%E1%86%BC
36. homework
• When a user logged in, move Vue Page and display user’s email using vuex
• tip>
<div v-if=“getFireUser">~~</div>
computed: {
...mapGetters(["getFireUser", "isUserAuth"])
},
<div class="text-h6" align="center">
Hi,({{ getFireUser.email }})
</div>
import { mapGetters } from "vuex";
44. Homework
• When a user logged in, move page(/home) and display user’s name using vuex
- user name was saved at Firestore, so we have to read the data
fi
rst to show it.
• user name should be displayed on page(/home) even after refreshing page.
69. Homework
• save user login timestamps to
fi
restore
• display user login info (w/ timestamp)
build your own table
70. q-table
• save user data to Firestore
var cdate = Date.now()
// firestore insert => then we can get doc id to generate qr code
db.collection("qrgen").add({
date: cdate,
id: this.getFireUser.email,
status: this.sliderValue //this.group
})
.then((docRef) => {
// console.log("Document written with ID: ", docRef.id);
})
.catch((error) => {
console.error("Error adding document: ", error);
});
77. q-table
• additional function - csv export
wrapCsvValue (val, formatFn) {
let formatted = formatFn !== void 0
? formatFn(val)
: val
formatted = formatted === void 0 || formatted === null
? ''
: String(formatted)
formatted = formatted.split('"').join('""')
/**
* Excel accepts n and r in strings, but some other CSV parsers do not
* Uncomment the next two lines to escape new lines
*/
// .split('n').join('n')
// .split('r').join('r')
return `"${formatted}"`
},
import { exportFile } from 'quasar'
81. androidstudio
• install
• license package download after installation
https://devvkkid.tistory.com/204
• build
• run (w/ AVD manager)
82. cordova
• npm install -g cordova
• quasar dev -m android --ide
android studio error might be occurred :
“Installed Build Tools revision 31.0.0 is corrupted. Remove and install again using the SDK Manager.”
if you get above error, then you should modify version settings in your build.grade as below image
then type below command on your terminal (https://stackover
fl
ow.com/questions/68387270/android-studio-error-installed-build-tools-revision-31-0-0-is-corrupted)
cd ~/Library/Android/sdk/build-tools/31.0.0 && mv d8 dx && cd lib && mv d8.jar dx.jar
then close android studio and re-run “quasar dev -m android —ide"
88. BasicStructure
• setup is called between “before created” and “created”
• you can set a style whatever you want
step 1
<template>
<div class="test">
Hello World, {{ name }}
</div>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
name: 'PageIndex',
setup() {
const name = "KOPO"
return {
name
}
}
})
</script>
<style lang="scss">
.test {
color: red;
background-color: yellow;
text-align: center;
font-size: 30px;
}
</style>
89. BasicStructure
• add function “printName”
add a function
<template>
<div class="test">
Hello World, {{ name }}
<p></p>
{{ printName() }}
</div>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
name: 'PageIndex',
setup() {
const name = "KOPO"
const printName = () => {
return name + "!!"
}
return {
name,
printName
}
}
})
</script>
90. BasicStructure
• add a parameter : param
• call the function with parameter
add a parameter
<template>
<div class="test">
Hello World, {{ name }}
<p></p>
{{ printName(name) }}
</div>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
name: 'PageIndex',
setup() {
const name = "KOPO"
const printName = (param) => {
return 'hello '+ param + "!!"
}
return {
name,
printName
}
}
})
</script>
91. BasicStructure
• we want to change name string when a button is clicked.
but, the result is …
• tip> button width dynamically can be set.
use $ref !
add a button
<template>
<div class="test" ref="topitem">
Hello World, {{ name }}
<p></p>
{{ printName(name) }}
</div>
<q-btn
@click="changeName"
class="button is-primary"
color="primary"
label="BUTTON"
:style="{width: itemWidth+'px'}" />
</template>
<script>
import { defineComponent, ref } from 'vue';
export default defineComponent({
name: 'PageIndex',
mounted() {
this.itemWidth = this.$refs.topitem.clientWidth
console.log(this.itemWidth)
},
setup() {
let name = "KOPO"
let itemWidth = ref(0)
const printName = (param) => {
return 'hello '+ param + "!!"
}
const changeName = () => {
name = "Button Clicked"
console.log("name chaged? ", name)
}
return {
name,
itemWidth,
printName,
changeName
}
}
})
</script>
<style lang="scss">
.test {
color: red;
background-color: yellow;
text-align: center;
font-size: 30px;
width: 300px;
}
</style>
92. BasicStructure
• “KOPO” —> ref(“KOPO”)
• name —> name.value
use ref to make the variable to be reactive
setup() {
let name = ref("KOPO")
let itemWidth = ref(0)
const printName = (param) => {
return 'hello '+ param + "!!"
}
const changeName = () => {
name.value = "Button Clicked"
console.log("name chaged? ", name)
}
if you use object or array data, use reactive(“~”) instead ref(“~”)