How to use vue components in nativescript-vue popups? - javascript

I open the popup in some root component like this:
import parentt from "./parentt.vue";
.
.
.
this.$showModal(parentt, {
fullscreen: true,
});
This is the content of parentt.vue:
<template>
<StackLayout>
<label text="parent" />
<!-- <child /> -->
</StackLayout>
</template>
<script>
import child from "./child.vue";
export default {
components: [child],
};
</script>
<style scoped>
</style>
This is the content of child.vue:
<template>
<StackLayout>
<label text="child" />
</StackLayout>
</template>
<script>
export default {};
</script>
<style scoped></style>
Whith <child /> commented out I get a popup with text parent in it.
with <child /> being there I get a white screen.
I'm using many components in different places in my code, it's only here in a popup that it doesn't work.

You have wrong bracket in components object in parentt.vue. Components is an object, thus use braces instead of the square brackets.
So, the correct script section looks like in parentt.vue:
<script>
import child from "./child.vue";
export default {
components: {
child
},
};
</script>
I recommend for detailed informations the official vue documentation

Related

Why do these Vue props fail outside the main component?

I am working on a Vue 3 app. I have run into a problem working with a <Navbar /> component and one of its sub-components.
In App.vue:
<template>
<Navbar />
<Content title="Home" />
<Footer />
</template>
<script>
import Navbar from './components/Navbar.vue'
import Content from './components/Content.vue'
import Footer from './components/Footer.vue'
export default {
name: 'App',
components: {
Navbar,
Content,
Footer
}
}
</script>
Within the Content.vue component, I can display the title this way:
<h1>{{ title }}</h1>
<script>
export default {
name: 'Content',
props: {
title: String
}
}
</script>
But displaying buttons with their labels by the same pattern as above does not work:
// Button.vue component
<template>
<button class="btn btn-sm btn-generate">
{{ label }}
</button>
</template>
<script>
export default {
name: 'Button',
props: {
label: String
}
}
</script>
// Navbar.vue component
<template>
<div class="navbar">
<Button label="Button 1" />
<Button label="Button 2" />
</div>
</template>
<script>
import Button from './Button'
export default {
name: 'Navbar',
components: {
Button
}
}
</script>
The problem
As a result of the code above, inside <div class="navbar"> there is only one button with no label, instead of 2 buttons labeled "Button 1" and "Button 2".
Where is my mistake?
I think that naming your component just as the already existing HTML element is not a good idea. Try changing it to MyButton and use <my-button>... in the navbar component (you still want to use <button> in MyButton, as you want to build upon it).
Most probably browser still picks just a default button instead of yours.
The first essential rule mentioned in Vue docs is Use multi-word component names.
You need to bind them so :label="button 1"

Using components on pages, layout always choosing default. Can not chose another layout

I have a problem of nuxt.js
When I try using components in some pages, and layout is 'something' (layout:'something').
But layout always applied default.
Is this a nuxt bug? or there some rules about it?
// pages/main.vue
<template>
<div>
<something />
</div>
</template>
<script>
import something from "#/components/something.vue";
export default {
components: {
something
},
layout: 'a'
};
</script>
.
.
.
// layouts/a.vue
<template>
<v-app class="dark">
<nuxt/>
</v-app>
</template>
<style scoped>
.dark {
background:black;
}
</style>
.
.
.
// components/something.vue
<template>
<div>
Hello
</div>
</template>
Add some paragraph to your layout and check out if its applied:
<template>
<v-app class="dark">
<p>Hello from layout</p>
<nuxt/>
</v-app>
</template>
Are you not suppose to import the v-app component to your layout and then export it?
<script>
import VApp from "#/components/../..
export default {
components: {
VApp
}
</script>
Of course, depending of the location of your v-app component

Detect from component if it is within certain DOM parent

I currently have a Vue.js application in which I have used my own component. I want HTML DOM children components to be able know if they are contained in my component or just in the application itself. What would the best way to do it?
I tried it using props, but as it is all contained within another application that does not seem possible.
example: I want the si-button to be able to determine that it is contained in a si-dialog. How do I pass that information to the si-button?
<si-dialog ref="siDialogChildren" name="children">
<div>
<h1>Hello children dialog!</h1>
<p>Click outside the dialog to close this dialog.</p>
</div>
<si-button id="test" type="custom" :on-click="buttonPress">
Click
</si-button>
</si-dialog>
Yours sincerely,
Mirijam
You might want to use $parent as specified in the Vue documentation.
For example, you can get the name of the parent component by accessing to its "$options.name" property.
Example:
App.vue
<template>
<div id="app">
<ParentComponent>
<ChildComponent />
</ParentComponent>
</div>
</template>
<script>
import ParentComponent from './components/ParentComponent'
import ChildComponent from "./components/ChildComponent";
export default {
name: 'App',
components: {
ParentComponent,
ChildComponent
}
}
</script>
<style>
</style>
ParentComponent.vue
<template>
<div>
<p>I'm a parent component.</p>
<slot></slot>
</div>
</template>
<script>
export default {
name: "ParentComponent",
props: {},
computed: {}
};
</script>
<style scoped>
</style>
ChildComponent.vue
<template>
<div>
<p>Parent name: {{componentName}}</p>
<p>I'm inside a ParentComponent? {{componentName === "ParentComponent" ? "Yes!" : "No."}}</p>
</div>
</template>
<script>
export default {
name: "ChildComponent",
computed: {
componentName() {
// We get the parent name from the $options.name property of our parent
// component
return this.$parent.$options.name
}
}
};
</script>
<style scoped>
</style>
NOTE You can also access to other properties on the parent component by using the $parent property. Try it out!

How to fix blank screen when trying to render components with ' :is="component" '

Writing in NativeScript-Vue for Android, I am trying to render a component based on button taps. I am using this this plugin to wrap the app in a global SideDrawer for quick navigation. I use buttons within the SideDrawer for viewing components. Here is what my App.vue looks like:
<template>
<Frame>
<Page actionBarHidden="true">
<GlobalDrawer>
<template slot="content">
<Label class="drawer-header" text="Drawer"/>
<Button class="drawer-button" text="Home" #tap="currentComponent = 'Home'" />
<Button class="drawer-button" text="Info" #tap="currentComponent = 'InfoPage'" />
<Button class="drawer-close-button" #tap="$drawer.close()">Close</Button>
</template>
<template slot="frame">
<ContentView>
<component v-for="component in pagesArray" v-show="component === currentComponent" :is="component" v-bind:key="component" />
</ContentView>
</template>
</GlobalDrawer>
</Page>
</Frame>
</template>
<script>
import Home from './pages/Home.vue';
import InfoPage from './pages/InfoPage.vue';
export default {
data () {
return {
pagesArray: ['Home', 'InfoPage'],
currentComponent: 'Home'
};
},
components: {
Home,
InfoPage
}
}
</script>
Here is the code in Home.vue, the default component I try to render:
<template>
<Page>
<navigation-bar />
<GridLayout>
<Label class="info" horizontalAlignment="center" verticalAlignment="center">
<FormattedString>
<Span class="fa" text.decode=" "/>
<Span :text="message"/>
</FormattedString>
</Label>
</GridLayout>
</Page>
</template>
<script>
import NavigationBar from '../components/NavigationBar.vue';
export default {
computed: {
message() {
return "Test Homepage";
}
},
components: {
NavigationBar
}
};
</script>
If I directly use the <home /> component within <ContentView /> it displays fine, but when trying to display it dynamically, I get a blank page; no errors. Any thoughts on this?
I run the app on a connected Samsung Galaxy S7 using the NativeScript CLI. NativeScript-vue version: ^2.4.0.
Edit [01.20.20]: Detailed explanation on how I solved it.
Read about it here: https://nativescript-vue.org/en/docs/routing/manual-routing/
In Application.vue, my GlobalDrawer looks like this:
<GlobalDrawer >
<template class="global-drawer" slot="content">
<ScrollView orientation="vertical" scrollBarIndicatorVisible="true" height="100%">
<StackLayout orientation="vertical">
<Label class="drawer-header" text="Menu"/>
<Button class="drawer-button" text="Home" ref="homeButton" #tap="homePageTap"/>
<Button class="drawer-button" text="System Oversight" #tap="infoPageTap" />
<Button class="drawer-button" text="Companies" #tap="companiesPageTap" />
<Button class="drawer-button" text="Calendar" #tap="calendarPageTap" />
<Button class="drawer-close-button" #tap="$drawer.close()">Close</Button>
<Label class="drawer-footer" text="By Bouvet" />
</StackLayout>
</ScrollView>
</template>
<template slot="frame">
<frame-hub />
</template>
</GlobalDrawer>
The methods-section contains the #tap-methods:
methods: {
homePageTap(args) {
this.$navigateTo(Home, { frame: "main-frame" });
this.$drawer.close();
},
infoPageTap(args) {
this.$navigateTo(InfoPage, { frame: "main-frame" });
this.$drawer.close();
},
companiesPageTap(args) {
this.$navigateTo(CompaniesPage, { frame: "main-frame" });
this.$drawer.close();
},
calendarPageTap(args) {
this.$navigateTo(CalendarPage, { frame: "main-frame" });
this.$drawer.close();
}
},
The < frame-hub > is a component (FrameHub.vue), looking like this:
<template>
<Page actionBarHidden="true">
<Frame id="main-frame">
<home />
</Frame>
</Page>
</template>
<script>
import Home from './../pages/Home';
import InfoPage from './../pages/InfoPage.vue';
import CompaniesPage from './../pages/CompaniesPage.vue';
import CalendarPage from './../pages/Calendar.vue';
export default {
components: {
Home,
InfoPage,
CompaniesPage,
CalendarPage
}
}
</script>
The #tap-methods in Application.vue changes the components that are renderered within the"main-frame"-element in FrameHub.vue. This way the GlobalDrawer is always on top, while the user is free to switch between pages.
I hope this helps anyone having the same issue. Also I'm sure this solution can be improved. Though I'm not currently working on this, but please let me know about improvements.
Creator of nativescript-vue-global-drawer plugin here.
The frame slot of GlobalDrawer contains a Frame element (here) to control navigation inside the drawer as stated here, which means the slot accept only Page elements.

Variable is linked in two components vue js

I just want to use an independant component many times like this :
<main-component>
<other-component />
<other-component />
</main-component>
I have a problem with variable in my other-component.
In the code bellow I use show var to display or not content according button click. I want to display only the paragraph of the current component clicked
import otherComponent from '../../otherComponent'
// main component
export default {
name: 'main-component',
components: {
otherComponent
},
data () {
return {
}
},
}
<template>
<div>
<other-component />
<other-component />
</div>
</template>
// other component
export default {
name: 'other-component',
data () {
return {
show: false
}
},
methods: {
toggle(){
this.show = !this.show
}
}
<template>
<div>
<button #click="toggle">Toggle</button>
<p v-show="show">1</p>
</div>
</template
When I click in button the two p are displayed. Why ?
If you nest components inside one another, you need to use slots: https://v2.vuejs.org/v2/guide/components-slots.html#ad.
For the following code to render correctly:
<main-component>
<other-component />
<other-component />
</main-component>
Your main-component component needs to have <slot /> in it's template:
<template>
<div>
<slot />
</div>
</template>
Then <slot /> will be replaced by ...
<other-component />
<other-component />
...when it renders. Which means main-component does not need to import or have any reference to otherComponent.
I have an example on CodeSandbox of this working: https://codesandbox.io/embed/vue-template-gblx0.

Categories

Resources