Quasar: how to display an image when using q-file to pick the image? - quasar-framework

New to Quasar & Vue.
I am using q-file which allow pick file & drag to drop file.
However, how do i display the image for preview?
Q-uploader seems work but how do i change the ui of it?
Link to component from Quasar:
https://quasar.dev/vue-components/file-picker

In you template define a q-file and q-img element. Add a #change handler and updateFile function. The q-img will contain the picture you selected.
import { ref } from 'vue';
import { defineComponent } from 'vue';
<script lang="ts">
export default defineComponent({
name: 'Component Name',
components: {},
setup () {
const image = ref(null);
const image1Url = ref('')
return {
image,
image1Url,
updateFile() {
imageUrl.value = URL.createObjectURL(image.value);
}
}
}
})
</script>
<div>
<q-file
v-model="image"
label="Pick one file"
filled
style="max-width: 300px"
#change="updateFile()"
/>
</div>
<div>
<q-img
:src="imageUrl"
spinner-color="white"
style="height: 140px; max-width: 150px"
/>
</div>
Create an #change hook on q-file:
In the script set the url from the file passed in from q-file:

Related

Vue3 with ASP.NET MVC: Props not being passed in

I have an ASP.NET MVC application which I've inherited. The most recent new bits of functionality use custom Vue2 components. Each MVC view is effectively a Single Page Application as I understand it. Each view has its own index.js file e.g.
import Vue from "vue"
window.Vue = Vue
import Test from '#/components/test'
const vm = new Vue({
el: "#test",
components: {
Test
},
data() {
return {}
}
})
The top level component is a single file component e.g. Test.vue:
<template>
<div>
<h1>{{ message }}</h1>
</div>
</template>
<script>
export default {
name: 'Test',
props: {
message: {
type: String,
default: 'This has not worked'
}
}
}
</script>
The MVC view itself looks like:
#{
ViewBag.Title = "Test";
Layout = "~/Views/Shared/_MentorNet.cshtml";
}
<div id="test" v-cloak>
<test message="This has worked"></test>
</div>
#section scripts
{
<script src="#Url.Content("~/dist/js/test.js")" defer></script>
}
The /dist/js/test.js file is created as a result of running Webpack with vue-loader.
With Vue2 this works fine. In this example the text "This has worked" appears when the controller returns the view.
However I'm trying to upgrade to Vue3 and this isn't working. The index.js file now looks like:
import { createApp } from "vue"
import Test from '#/views/admin/test'
const app = createApp(Test);
app.mount("#test");
The component and the view are the same. The component is displayed but the props are not passed through - the view returns the text "This has not worked".
I've looked at the Vue2 migration guide and can't see any breaking changes that would affect this. Can anyone help please?
I've got the answer thanks to a response on the Vue Land Discord channel.
The problem was with the code in the index.js file:
const app = createApp(Test);
app.mount("#test");
When passing a component with a template/render function to createApp it completely overwrites the content of the mount target, in this case
<div id="test">
<test message="This has worked"></test>
</div>
so the
<test message="This has worked"></test>
isn't used. The correct way to do it is either to pass the props as the second argument of create App:
const app = createApp(Test, {
message: "This has worked"
});
or, and the way I'm going to be doing it:
const app = createApp({
components: { Test }
});

How do I use slots with a Quasar Dialog Plugin custom component?

I want to make a custom component for the Quasar Dialog. And inside that component I want to use slots, but I'm not sure how to do that.
This is my CustomDialogComponent.vue where I have defined a cancelBtn slot and a confirmBtn slot:
<template>
<!-- notice dialogRef here -->
<q-dialog ref="dialogRef" #hide="onDialogHide">
<q-card class="q-dialog-plugin">
<q-card-section>
<strong>{{ title }}</strong>
</q-card-section>
<q-card-section>
<slot name="cancelBtn" #click="handleCancelClick"></slot>
<slot name="confirmBtn" #click="handleConfirmClick"></slot>
</q-card-section>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import { PropType } from 'vue';
import { useDialogPluginComponent } from 'quasar';
defineProps({
title: {
type: String,
required: false,
default: 'Alert',
},
});
defineEmits([
...useDialogPluginComponent.emits,
]);
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
useDialogPluginComponent();
const handleConfirmClick = () => {
console.log('Confirm Button Clicked');
onDialogOK();
};
const handleCancelClick = () => {
console.log('Cancel Button Clicked');
onDialogCancel();
};
</script>
And the Quasar docs show that I can invoke it via a $q.dialog({ ... }) Object. With props etc all set inside that object. So that would look something like this:
<template>
<div #click="showDialog">Show The Dialog</div>
</template>
<script setup lang="ts">
import { useQuasar } from 'quasar';
import CustomDialogComponent from 'src/components/CustomDialogComponent.vue'
const $q = useQuasar();
const showDialog = () => {
$q.dialog({
component: CustomDialogComponent,
// props forwarded to your custom component
componentProps: {
title: 'Alert title goes here',
},
})
};
</script>
But there are no properties inside the Dialog Object for me to pass in my slots. So where can I pass in the cancelBtn and confirmBtn slots I created in CustomDialogComponent.vue?
I asked directly and apparently there is no way to use slots at this time. They might add this functionality later.

How to turn off the hover effect in Expansion Item component in Quasar framework?

How to turn off the hover effect in Expansion Item component in Quasar framework? And how can I remove the default arrow? I don’t need it at all.
To remove the expansion icon, just give it expand-icon="0". And to remove the hover effect, use CSS to hide the q-focus-helper class.
<template>
<q-page class="flex flex-center">
<q-expansion-item
expand-icon="0"
v-model="expansionState"
>
<p>Some content 1</p>
<p>Some content 2</p>
</q-expansion-item>
</q-page>
</template>
<script>
export default {
name: 'PageIndex',
data() {
return {
expansionState: true,
};
},
};
</script>
<style lang="scss">
.q-expansion-item {
.q-focus-helper {
visibility: hidden;
}
}
</style>
I make it work by setting the css under app.scss, not inside the component itself.
.q-expansion-item {
.q-focus-helper {
visibility: hidden;
}
}

Select one class in a Svelte component?

<script>
export let text
</script>
<button>
{text}
</button>
<style>
:global(.bg-primary) {
background-color: red ;
}
:global(.bg-secondary {
background-color: blue;
}
</style>
When I import my component inside another component I would like to setup the background color with a prop
<script>
export let text
export let type = 'secondary'
</script>
<button class="bg-{type}">
{text}
</button>
or
<button class:bg-primary={type === 'primary'} class:bg-secondary={type === 'secondary'}>
{text}
</button>
The second approach limits the number of classes and works better with svelte unused class checking.

Change image onclick-events

How do I implement a button on-click event with loading different images?
I want to show different images in one div-container. If I click on the button "changeImage" it should change the picture.
How can I implement this in dart language?
Update: A new image should be loaded by each click. The images are in one file.
Do I call the img with a Button like this?
<input type="button" value="button" ng-click="img">
depending on the answer to my comment above there are different ways to do it.
(not tested)
import 'dart:async';
const NUM_IMAGES = 4;
main() {
int curImg = 1;
(querySelectorAll('img') as HtmlElement).forEach((img) {
img.onClick.listen((e) {
(querySelector('#img_${curImg % 4}') as HtmlElement).classes.add('hidden');
curImg++;
(querySelector('#img_${curImg % 4}') as HtmlElement).classes.remove('hidden');
});
}
.
<style>
img.hidden {
display: none;
}
</style>
<img id="img_1" src="a.gif" >
<img id="img_2" src="b.gif" class="hidden">
<img id="img_3" src="c.gif" class="hidden">
<img id="img_4" src="d.gif" class="hidden">
alternative solution:
List<String> uris = ['/img/img_a.gif', '/img/img_b.gif', '/img/img_c.gif', '/img/img_d.gif'];
main() {
int curImg = 0;
(imgElement = querySelector('img') as ImageElement).onClick.listen((img) {
curImg++;
imgElement.src = uris[curImg];
});
}
.
<img>

Resources