in this version of #ionic/vue#0.5.5.2 I can't use a component and assign a reference (< Login ref="modal"/>) to it to close it in the Modal component (Login.vue), so I don't know how to close it from Login.vue. I leave my code:
Home.vue
<template>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-title>
Title
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="auth-form">
<ion-grid>
<ion-row>
<ion-col align-self-center>
<ion-button #click="openModal" expand="block" color="primary">Registrarme</ion-button>
<span class="divider line one-line">o</span>
<span class="already">¿Tienes una cuenta?</span>
<ion-button #click="openModal" expand="block" color="danger">Iniciar sesión</ion-button>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
</ion-page>
</template>
<script>
import {
IonContent,
modalController,
IonTitle,
IonToolbar,
IonHeader,
IonButton,
IonCol,
IonRow,
IonGrid,
IonPage
} from '#ionic/vue';
import Login from '../views/Login.vue';
export default {
name: 'inicio',
components: {
IonContent,
IonTitle,
IonToolbar,
IonHeader,
IonButton,
IonCol,
IonRow,
IonGrid,
IonPage
},
data() {
return {
modal: '',
isOpen: false,
}
},
methods: {
async createModal() {
this.modal = await modalController.create({
component: Login,
componentProps: {
title: 'Iniciar sesión'
},
})
},
async openModal() {
await this.createModal()
this.isOpen = true
this.modal.present()
},
closeModal() {
this.isOpen = false
this.modal.dismiss().then(() => {
this.modal = null;
});
},
},
}
</script>
And my Login.vue:
<template>
<ion-page>
<ion-header translucent>
<ion-toolbar>
<ion-title>{{ title }}</ion-title>
<ion-buttons slot="end">
<ion-button #click="cerrarmodal">Cerrar</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item>
<ion-label>Email</ion-label>
<ion-input type="text"></ion-input>
</ion-item>
<ion-item>
<ion-label>Contraseña</ion-label>
<ion-input type="password"></ion-input>
</ion-item>
</ion-list>
<ion-button color="primary" expand="block">Ingresar</ion-button>
</ion-content>
</ion-page>
</template>
<script>
import {
IonButtons,
IonContent,
IonButton,
IonToolbar,
IonHeader,
IonTitle,
IonList,
IonLabel,
IonInput,
IonItem,
IonPage
} from '#ionic/vue';
import {
defineComponent
} from 'vue';
export default defineComponent({
name: 'login',
props: {
title: {
type: String,
default: 'Super Modal'
},
closeMe: {
type: Function,
default: () => {
''
}
},
},
data() {
return {
content: 'Content',
}
},
methods: {
cerrarmodal() {
this.$emit('close', {
foo: 'bar'
})
// Not working
this.$parent.closeModal()
},
},
components: {
IonButton,
IonButtons,
IonToolbar,
IonList,
IonInput,
IonLabel,
IonItem,
IonPage,
IonHeader,
IonTitle,
IonContent
},
});
</script>
I've tried $ emit and $ parent.closeModal () but no luck, thanks for your help in advance.
I confirm that the best and simple way to solve this is calling dismiss() function of modalController.
First we must import modalController in our modal component:
import { modalController } from "#ionic/vue";
Next we can close modal like this:
async function close() {
await modalController.dismiss();
}
Important: I use await because dismiss return a promise so it's important use it.
I resolved it by passing a prop "close" with the function closeModal and defining the prop "close" in the modal component and then calling it with a this.close
this.modal = await modalController.create({
component: Login,
componentProps: {
title: 'Iniciar sesión',
close: () => this.closeModal()
},
})
In modal component:
props: {
title: {
type: String,
default: 'Super Modal'
},
close: { type: Function }
},
cerrarmodal() {
this.$emit('close', {
foo: 'bar'
})
this.close()
},
I think you can call
modalController.dismiss()
to close any open dialog... also the emit should have worked, didn't see that code
<!-- ./modal.vue -->
<template>
<ion-header>
<ion-toolbar>
<ion-button shape="round" fill="clear" #click="modalController.dismiss()">
<ion-icon slot="icon-only" :icon="arrowBackOutline" />
</ion-button>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
{{ content }}
</ion-content>
</template>
<script lang="ts">
import { IonButton, IonHeader, IonToolbar, IonContent } from '#ionic/vue';
import { arrowBackOutline } from 'ionicons/icons';
import { modalController } from "#ionic/vue";
export default {
name: 'Modal',
components: { IonButton, IonHeader, IonToolbar, IonContent },
setup(){
const content = 'Content';
return {
content,
modalController,
arrowBackOutline,
IonHeader,
IonToolbar
}
}
}
</script>
Related
I've those two components using Nuxt 3.
The setActive method in component 1 changes the state of activeColor, but the cancelEdit method in component 2 does not.
Any idea why this is the case?
Component 1
Here the setActive method changes activeColor:
<template>
<div class="f-button" #click="addColor">+ Add Color</div>
{{ activeColor }}
<div class="f-colors">
<Color v-for="color in colors" :color="color" :edit="activeColor === color" #click="setActive(color)"/>
</div>
</template>
<script>
import {useProjectStore} from "~/stores/projects";
import {storeToRefs} from "pinia";
import Color from "~/components/Color.vue";
export default defineComponent({
name: "ColorManagement",
components: {Color},
setup() {
const projectStore = useProjectStore()
const { getColors, getActiveColor } = storeToRefs(projectStore);
return {
projectStore,
colors: getColors,
activeColor: getActiveColor
};
},
methods: {
addColor() {
...
},
setActive(color) {
this.projectStore.$patch({ activeColor: color })
}
}
});
</script>
Component 2
Here the cancelEdit method doesn't change activeColor:
<div class="f-color">
<div class="f-color__actions" v-if="edit">
<div class="f-color__action" #click="cancelEdit">
<Cancel /><span>Cancel</span>
</div>
</div>
</div>
</template>
<script>
import Cancel from "~/components/icons/Cancel.vue";
import {useProjectStore} from "~/stores/projects";
import {storeToRefs} from "pinia";
export default defineComponent({
name: "Color",
components: {Cancel},
props: ["color","edit"],
setup() {
const projectStore = useProjectStore()
const { activeColor } = storeToRefs(projectStore);
return {
projectStore,
activeColor
};
},
methods: {
cancelEdit() {
this.projectStore.$patch({ activeColor: false })
}
}
});
</script>
nuxt.config.ts
export default defineNuxtConfig({
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '#use "#/assets/styles/_styles.scss" as *;'
}
}
}
},
modules: ['#pinia/nuxt']
})
Store
import { defineStore } from "pinia";
export const useProjectStore = defineStore({
id: 'project',
state: () => {
return {
project: {
colors: [{ color: false, name: '' }]
},
activeColor: null
}
},
getters: {
getColors(state){
return state.project.colors || [];
},
getActiveColor(state){
return state.activeColor;
}
}
});
Ok, if I got this correctly, the deal is this:
Your so called Component 2 is the <Color ... component being used in Component 1, right?
When you trigger cancelEdit inside Component 2 (aka Color) you are also triggering the logic from setActive due to this <Color ...#click="setActive(color)"...so your activeColor is set to false (from the cancelEdit method) but right after it is set to active again, got it?
To fix this (if you don't want to change your HTML structure) you can use events stopPropagation method inside the cancelEdit:
cancelEdit(e) {
e.stopPropagation()
this.projectStore.$patch({ activeColor: false })
}
Event.stopPropagation() reference
I am seriously struggling to figure out how to layout the InAppBrowser in a small section of the screen.
I want to have a permament IonicToolbar above the InAppBrowser and eventually add my own navigation buttons.
I'm very new to Iconic/Vue and whatever I've tried so far just seems to show the browser on top of the IonToolbar and IonPage
BaseLayout
<template>
<ion-page>
<ion-header>
<ion-header>
<ion-toolbar>
<ion-title>Title</ion-title>
</ion-toolbar>
</ion-header>
</ion-header>
<ion-content>
<slot />
</ion-content>
</ion-page>
</template>
<script>
import {
IonPage,
IonHeader,
IonToolbar,
IonTitle,
IonContent,
} from "#ionic/vue";
export default {
props: ["pageTitle", "defaultBackLink"],
components: {
IonPage,
IonHeader,
IonToolbar,
IonTitle,
IonContent,
},
};
</script>
BrowserLayout
<template>
<in-app-browser></in-app-browser>
</template>
<script>
import { InAppBrowser } from "#ionic-native/in-app-browser";
function beforeloadCallBack(params, callback) {
console.log(">>> beforeload: " + params.url.toString());
if (params.url.includes("https://www.google.com/")) {
console.log(">>> beforeload: allowed");
callback(params.url);
} else {
console.log(">>> beforeload: restricted");
alert("The URL is restricted!");
}
}
export default {
components: {
InAppBrowser,
},
setup() {
const options = {
location: "no",
zoom: "no",
hardwareback: "yes",
mediaPlaybackRequiresUserAction: "no",
hidenavigationbuttons: "yes",
hideurlbar: "yes",
toolbar: "no",
fullscreen: "no",
beforeload: "yes",
};
let browser = InAppBrowser.create(
"https://www.google.com",
"_blank",
options
);
browser.on("loadstop").subscribe((event) => {
console.log(">>> onLoadStop:" + event.url.toString());
});
browser.on("loadstart").subscribe((event) => {
console.log(">>> onLoadStart:" + event.url.toString());
});
browser.on("beforeload").subscribe((params) =>
beforeloadCallBack(params, () => {
return params.url;
})
);
},
};
</script>
HomePage
<template>
<base-layout>
<browser-layout></browser-layout>
</base-layout>
</template>
<script>
import BrowserLayout from "#/components/browser/BrowserLayout.vue";
import BaseLayout from "#/components/base/BaseLayout.vue";
export default {
components: {
BaseLayout,
BrowserLayout,
},
};
</script>
Im build project on forntend vue and backend django. I stuck with problem what i can't resolv.
I trying to send data from ProjectsView.vue to ProjectDetailView.vue. Im trying to use props but i get error:
[Vue warn]: Missing required prop: "slug"
ProjectsView.vue don't send data to ProjectDetailView.vue and axios throw a error
GET http://127.0.0.1:8000/api/v1/projectdetail/undefined/ 500 (Internal Server Error)
I can't find problem in this code.
this is my ProjectsView:
<template>
<div class="container d-flex d-xl-flex justify-content-xl-center">
<div class="d-flex d-sm-flex d-md-flex d-lg-flex d-xl-flex justify-content-center flex-wrap justify-content-sm-center justify-content-md-center justify-content-lg-center justify-content-xl-center">
<div v-for="prof in projects" v-bind:key="prof.id">
<div class="card" style="width: 285px;height: 400px;margin: 5px;border-radius: 15px;">
<div class="card-body text-center">
<img class="img-fluid" :src="prof.avatar" style="width: 150px;border-width: 1px;border-radius: 100px;" />
<h4 class="card-title">
<router-link
:to="{ name: 'projectdetail', params: { slug: prof.slug } }"
>{{ prof.title }}
</router-link>
<fa v-if="prof.is_online" icon="circle" data-bs-toggle="tooltip" title="Online" style="color: rgb(0,197,67);font-size: 12px;padding: 0px;margin-top: 0px;" /></h4>
<h6 class="text-muted card-subtitle mb-2">{{ prof.about }}</h6>
<h6 class="text-muted card-subtitle mb-2">{{ prof.last_online_at }}</h6>
<div v-if="prof.tahs">
<div class="d-inline-block" v-for="tag in prof.tahs.split(',')" v-bind:key="tag">
<span class="badge rounded-pill bg-secondary" style="margin: 1px;">{{tag}}</span>
</div>
</div>
<p class="card-text"></p><a class="card-link" href="#">Link</a><a class="card-link" href="#">Link</a>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import { useToast } from "vue-toastification";
import Project from '#/views/DetailProjectView.vue'
export default {
name: 'Projects',
setup() {
// Get toast interface
const toast = useToast();
return { toast }
},
data() {
return {
projects: [],
errors: [],
}
},
mounted() {
this.getItemsProjects()
},
components: {
Project,
},
methods: {
async getItemsProjects() {
this.$store.commit('setIsLoading', true)
axios
.get('/api/v1/projects/')
.then(response => {
this.projects = response.data
console.log(this.projects)
})
.catch(error => {
console.log(error)
})
this.$store.commit('setIsLoading', false)
},
}
}
</script>
and this is my ProjectDetailView.vue
<template>
<div>working? {{slug}}
</div>
</template>
<script>
import axios from 'axios'
import { useToast } from "vue-toastification";
export default {
name: 'Project',
setup() {
// Get toast interface
const toast = useToast();
return { toast }
},
data() {
return {
project: [],
errors: [],
}
},
mounted() {
this.getItemsProjects()
},
props: {
slug: {
type: String,
required: true,
},
},
methods: {
async getItemsProjects() {
this.$store.commit('setIsLoading', true)
axios
.get(`/api/v1/projectdetail/${this.slug}`)
.then(response => {
this.project = response.data
console.log(this.project)
})
.catch(error => {
console.log(error)
})
this.$store.commit('setIsLoading', false)
},
}
}
</script>
and my router:
import { createRouter, createWebHistory } from 'vue-router'
import store from '../store'
import HomeView from '../views/HomeView.vue'
import Signup from '../views/SignupView.vue'
import Login from '../views/LoginView.vue'
import Dash from '../views/DashView.vue'
import Myacc from '../views/MyAccView.vue'
import Profile from '../views/ProfileView.vue'
import Projects from '../views/ProjectsView.vue'
import ProjectDetail from '../views/DetailProjectView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/signup',
name: 'signup',
component: Signup
},
{
path: '/login',
name: 'login',
component: Login
},
{
path: '/dash',
name: 'dash',
component: Dash,
meta: {
requiredLogin: true
}
},
{
path: '/myacc',
name: 'myacc',
component: Myacc,
meta: {
requiredLogin: true
}
},
{
path: '/profile',
name: 'profile',
component: Profile,
meta: {
requiredLogin: true
}
},
{
path: '/projects',
name: 'projects',
component: Projects,
meta: {
requiredLogin: true
}
},
{
path: '/project/:slug',
name: 'projectdetail',
component: ProjectDetail,
meta: {
requiredLogin: true,
}
},
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiredLogin) && !store.state.isAuthenticated) {
next('/login')
} else {
next()
}
})
export default router
how to fix this bug? thank you for advice.. im new in vue
edit
I have got a wrapper around a package called vue-awesome-swiper, as follows:
Slider.vue
<template>
<div class="media-slider">
<slot :sliderSetting="sliderSettings" :name="name">
<swiper :options="sliderSettings[name]"
class="swiper"
v-if="slides"
ref="default-slider">
<slot name="slides" :slides="slides" :code="code">
<swiper-slide v-for="image in slides" :key="image" v-if="endpoint"
:style="{'background-image': `url('${image}')`}">
</swiper-slide>
</slot>
<div class="swiper-button-next swiper-button-white" slot="button-next"></div>
<div class="swiper-button-prev swiper-button-white" slot="button-prev"></div>
<div class="swiper-pagination" slot="pagination"></div>
<div class="swiper-scrollbar" slot="scrollbar"></div>
</swiper>
</slot>
</div>
</template>
<script>
import { Swiper, SwiperSlide } from 'vue-awesome-swiper';
import 'swiper/css/swiper.css';
import Axios from '../../../../axiosConfig';
// https://github.surmon.me/vue-awesome-swiper/
export default {
components: { Swiper, SwiperSlide },
data: function() {
return {
code: null,
images: [],
defaults: {
'default-slider': {
loop: true,
loopedSlides: 5,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev'
},
scrollbar: {
el: '.swiper-scrollbar',
hide: true
}
}
},
sliderSettings: {}
}
},
props: {
endpoint: {
type: String,
default: null
},
settings: {
type: Object,
default: {}
},
theme: {},
name: {},
hash: {},
numberOfImages: {},
imageFormat: {},
vehicleId: {}
},
computed: {
slides() {
if (this.images.length) {
return this.images;
}
return [...Array(parseInt(this.numberOfImages))].map(
(_, i) => {
i++;
return this.imageFormat.replace('#', i);
}
);
}
}
}
</script>
As you can see I have got a slot within this component, however it must use an instance of SwiperSlide for it to work. I need to register this as a component to use it.
However this isn't working as expected:
Vue.component('slider', () => import('./components/Media/Slider/Index'));
Vue.component('slide', () => import('vue-awesome-swiper'));
How can I do this?
Edit
<slider class="app">
<template v-slot:slides="props">
<slide :style="{'background-image': `url('img-src/${props.code}/theme/slide-1.jpg')`}"></slide>
</template>
</slider>
An import like this import() is gonna import the default export of the package, what you have done here is that you have destructured the import with import { .. } from ".." that means it has an named export.
However try it like this
Vue.component('slider', () => import('./components/Media/Slider/Index'));
Vue.component('slide', async () => (await import('vue-awesome-swiper')).SwiperSlide);
I am having an issue with calling a parent function:
Error in v-on handler: "TypeError: self.$parent.testAddCompontnet222 is not a function"
So i have setup a test function (method) in the following file called testAddCompontnet222()
parent file: PageAdd.vue
<template>
<b-container>
<b-container>
testVar2: (( {{ testVar2 }} ))
<b-button #click="testAddCompontnet222();">Add Test 2</b-button>
<SingleBlockTemplate v-if="componentTypeSelected == 1"></SingleBlockTemplate>
<TripleBlockTemplate v-if="componentTypeSelected == 2"></TripleBlockTemplate>
</b-container>
</b-container>
</template>
<script>
import axios from 'axios';
import SingleBlockTemplate from './component_templates/SingleBlockTemplate.vue';
import TripleBlockTemplate from './component_templates/TripleBlockTemplate.vue';
import ComponentAddForm from './ComponentAddForm.vue';
export default {
data(){
return {
title: 'Case Studies',
excerpt: 'some text here for reference',
slug: 'unique',
meta_title: 'title for search engines (should be the same as the page title)',
meta_description: 'meta descriptions for search engines',
meta_keywords: 'keywords',
order: '1',
status: '1',
showAddComponentForm: false,
error: false,
errors: {},
testVar2: '2',
newContentData: {},
componentTypeSelected: '2',
componentTypes: {},
componentList: {}
};
},
mounted: function () {
this.getComponentTypes();
//this.componentTypeToCreate =
},
methods: {
testAddCompontnet222(){
this.testVar2 = '222!';
console.log("test 222222!")
},
addPage(){
axios({
method: 'post',
url: this.$appAPI+'/twg-cms/page',
data: {
title: this.title,
excerpt: this.excerpt,
slug: this.slug,
meta_title: this.meta_title,
meta_description: this.meta_description,
meta_keywords: this.meta_keywords,
order: this.order,
status: this.status
}
}).then(response => {
console.log(response.data)
}).catch(e => {
console.log(e)
this.errors.push(e)
});
},
getComponentTypes(){
axios.get(this.$appAPI+`/twg-cms/component_types`)
.then((response) => {
this.componentTypes = response.data.data;
})
.catch(() => {
console.log('handle server error from here');
});
},
componentTypeOnChange(value){
//console.log(this.componentTypeSelected)
}
},
components: {
ComponentAddForm,
SingleBlockTemplate,
TripleBlockTemplate
}
}
</script>
I then attempt to call the function from a child element (imported file): TripleBlockTemplate.vue
I have tried using just this.$parent.testAddCompontnet222(); and as you can see below currently self.$parent.testAddCompontnet222();
But both return the same error. I have this working in exactly the same way on other components
<template>
<form autocomplete="off" #submit.prevent="addComponent" method="post">
<b-button #click="testAddCompontnet();">Add Test</b-button>
<p>This is a triple block component</p>
<ckeditor :editor="editor" v-model="content[0]" :config="editorConfig"></ckeditor>
<ckeditor :editor="editor" v-model="content[1]" :config="editorConfig"></ckeditor>
<ckeditor :editor="editor" v-model="content[2]" :config="editorConfig"></ckeditor>
<b-button #click="addComponent" variant="outline-primary">Save component</b-button>
</form>
</template>
<script>
import axios from 'axios';
import ClassicEditor from '#ckeditor/ckeditor5-build-classic';
export default {
data(){
return {<template>
<form autocomplete="off" #submit.prevent="addComponent" method="post">
<b-button #click="testAddCompontnet();">Add Test</b-button>
<p>This is a triple block component</p>
<ckeditor :editor="editor" v-model="content[0]" :config="editorConfig"></ckeditor>
<ckeditor :editor="editor" v-model="content[1]" :config="editorConfig"></ckeditor>
<ckeditor :editor="editor" v-model="content[2]" :config="editorConfig"></ckeditor>
<b-button #click="addComponent" variant="outline-primary">Save component</b-button>
</form>
</template>
<script>
import axios from 'axios';
import ClassicEditor from '#ckeditor/ckeditor5-build-classic';
export default {
data(){
return {
editor: ClassicEditor,
name: 'Name here',
class: 'Class here',
html_id: 'ID here',
content:[
'<div><h1>Title 1</h1><br /><p>some simple text here</p></div>',
'<div><h1>Title 2</h1><br /><p>some simple text here</p></div>',
'<div><h1>Title 3</h1><br /><p>some simple text here</p></div>'
],
editorConfig: {
// The configuration of the editor.
}
};
},
methods: {
testAddCompontnet(){
var self = this;
self.$parent.testAddCompontnet222();
console.log("test 222!")
},
addComponent(){
axios({
method: 'post',
url: this.$appAPI+'/twg-cms/component',
data: {
name: this.name,
content: JSON.stringify({content: this.content}),
class: this.class,
html_id: this.html_id
}
}).then(response => {
console.log(response.data)
}).catch(e => {
console.log(e)
this.errors.push(e)
});
}
}
}
</script>
editor: ClassicEditor,
name: 'Name here',
class: 'Class here',
html_id: 'ID here',
content:[
'<div><h1>Title 1</h1><br /><p>some simple text here</p></div>',
'<div><h1>Title 2</h1><br /><p>some simple text here</p></div>',
'<div><h1>Title 3</h1><br /><p>some simple text here</p></div>'
],
editorConfig: {
// The configuration of the editor.
}
};
},
methods: {
testAddCompontnet(){
var self = this;
self.$parent.testAddCompontnet222();
console.log("test 222!")
},
addComponent(){
axios({
method: 'post',
url: this.$appAPI+'/twg-cms/component',
data: {
name: this.name,
content: JSON.stringify({content: this.content}),
class: this.class,
html_id: this.html_id
}
}).then(response => {
console.log(response.data)
}).catch(e => {
console.log(e)
this.errors.push(e)
});
}
}
}
</script>
Finally here is a working method which i am currently not using...
The following code, would allow me to use the same/similar code to update/change the parent variable testVar1 to update it's parent: ComponentAddForm.vue below
testAddCompontnet(){
var self = this;
self.$parent.testVar1 = '11111! test;
console.log("test 222!")
},
ComponentAddForm.vue:
<template>
<b-container>
testVar1: (( {{ testVar1 }} ))
<b-button #click="testAddCompontnet222();">Add Test 2</b-button>
<SingleBlockTemplate v-if="this.componentTemplateId == 1"></SingleBlockTemplate>
<TripleBlockTemplate v-if="this.componentTemplateId == 2"></TripleBlockTemplate>
</b-container>
</template>
<script>
import axios from 'axios';
import SingleBlockTemplate from './component_templates/SingleBlockTemplate.vue';
import TripleBlockTemplate from './component_templates/TripleBlockTemplate.vue';
export default {
props: ['componentTemplateId'],
data(){
return {
name: 'Case Studies',
testVar1: '1'
};
},
mounted: function () {
this.showComponentTemplate();
},
methods: {
testAddCompontnet222(){
this.$parent.testVar2 = '222!';
console.log("we made it here <--------");
},
showComponentTemplate(){
if(this.componentTemplateId === '1'){
console.log('test 1')
}
if(this.componentTemplateId === '2'){
console.log('test 2')
}
}
},
components: {
SingleBlockTemplate,
TripleBlockTemplate
}
}
</script>