I am trying to implement popover functionality for one of my mobile app where I need popover with an arrow on different players icon and display info. of a player in a popover. for this after some R & D, I found that I can use this plugin nativescript-popup. But I am unable to see a popup when I try to implement it. Here are my codes. It's not giving any error but it's not opening any popup too.
Home.vue
<template>
<Page actionBarHidden="true">
<Button #tap="openPopup" ref="btn" style="width:100;height:40;"/>
</Page>
</template>
<script>
import { StackLayout } from 'tns-core-modules/ui/layouts/stack-layout';
import { Label } from 'tns-core-modules/ui/label';
import { ScrollView } from 'tns-core-modules/ui/scroll-view';
import { Popup } from 'nativescript-popup';
import Test from './Test'
export default {
components: {
Test
},
data() {
return {
popup: Popup
}
},
methods: {
_showPopup(source, view) {
this.popup = new Popup({
height: 30,
width: 80,
unit: '%',
elevation: 10,
borderRadius: 25
});
this.popup.showPopup(source, view).then(data => {
console.log('aaaa',data);
}).catch(error => {
console.log('aaaa',error);
});
},
openPopup(arg) {
//this._showPopup(this.$refs.btn.nativeView, Test);
const stack = new StackLayout();
stack.height = '100%';
const lbl = new Label();
lbl.text = 'Osei';
stack.addChild(lbl);
const sv = new ScrollView();
sv.content = stack;
this._showPopup(this.$refs.btn.nativeView, sv);
}
}
</script>
Test.vue
<template>
<StackLayout>
<Label text="NativeScript is the bomb.com" color="#ff4801" fontSize="22" textWrap="true"></Label>
</StackLayout>
</template>
Please suggest to me what am I doing wrong? Any help will be appreciated.
Notes: After openPopup() function code update, its working and popup is opening correctly. How can I use it with directly with the Vue component(Test.vue) instead of creating a view inside a function?
This plugin do not have explicit support for Vue so you can not pass Test which I guess a Vue Component, you have to either pass a {N} View or native view instance.
Edit: You could pragramatically create the instance of Vue component and pass the nativeView of root element to your popup.
Playground Sample
Related
I am using NS 6.0 Core. Testing on a physical Android device (have not tried this on iOS yet).
In a nutshell, I have nested components and in the inside component, I want to capture a custom event and pass it to the host component.
Inside component (called TopBar):
<StackLayout padding="10" orintation="horizontal" loaded="onLoaded">
<Label text="" class="wa" fontSize="24" vertcalAlignment="middle" tap="back" />
</StackLayout>
import { StackLayout } from 'tns-core-modules/ui/layouts/stack-layout';
import { EventData } from 'tns-core-modules/ui/core/view/view';
var stack: StackLayout;
let eventData: EventData = {
eventName: "onBackEvent",
object: stack
}
export function onLoaded(args) {
stack = <StackLayout>args.object;
}
export function back() {
stack.notify(eventData);
}
The host component
import { Page } from "tns-core-modules/ui/page/page";
import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout/stack-layout";
import { EventData, Observable } from "tns-core-modules/data/observable";
var model: Observable = new Observable();
var page: Page;
export function onLoaded(args: EventData) {
page = <Page>args.object;
var topBar: StackLayout = page.getViewById('topBar');
topBar.on('onBackEvent', () => {
console.log('go back');
});
page.bindingContext = model;
}
<Page xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:tb="components/shared/top-bar/top-bar" loaded="onLoaded" actionBarHidden="true">
<GridLayout rows="*, 75" columns="*">
<StackLayout class="page-content">
<tb:TopBar id="topBar" height="50"></tb:TopBar>
</StackLayout>
</GridLayout>
</Page>
Any ideas on what I might be missing?
Thanks
{N} automatically trims event names starting with on, hence onBackEvent will be recorded as BackEvent only. So notifying onBackEvent will not have any effect.
In my opinion it makes sense, also when I checked last time Angular didn't use to support event names prefixed with on with event binding. That could also be a reason they had to force this as a standard measure.
So, after hours of trial and error, I manage to make it work.
The issue is that when notifying the client, we have to declare the EventData object as such:
let eventData: EventData = {
eventName: "BackEvent",
object: stack
}
Note that we capture the event by subscribing to onBackEvent but setting up the event name as BackEvent. I am not sure why this works or where in the documentation it is written, but this change did the job.
If anyone has more information about this, please post it here so we can all learn.
Thanks.
I am new to react. I am using react-route-dom and . I would like to change the colour of my NavBar functional component when the route changes.
In my NavBar component I am using the HOC (connect) from react-redux and withRouter from react-router to get route props and information from my redux store.
const mapStateToProps = (state) => {
return {
moduleCards: state.moduleCards
}
}
export default connect(mapStateToProps)(withRouter(NavBar));
Here is a snippet of how I am getting route information to then find the moduleCard entry and get it's colour.
const NavBar = (props) => {
console.log("Hello world?");
const modules = props.moduleCards.find(c => `/${c.name.replace(/ /g,'')}` === props.location.pathname);
const color = typeof modules !== 'undefined' ? modules.color : 'blue';
return (
<nav>
<div className={`nav-wrapper ${color} darken-2`}>
The problem is that the colour does not change when I change route. Can you please help with how to trigger a render on my NavBar component? Or if there is a better way to handle this?
Here is my root App component.
class App extends Component {
render() {
return (
<BrowserRouter>
<div className="App">
<NavBar/>
<Switch>
<Route exact path='/' component={Home}/>
<ModuleRoutes/>
</Switch>
</div>
</BrowserRouter>
);
}
}
Here is a snap shot of my store, this is where I am grabbing the colour from.
const initialState = {
moduleCards: [
{ id: 0, name: 'Client Register', icon: 'person', color: 'red' },
{ id: 1, name: 'Property Register', icon: 'domain', color: 'blue' },
The colour is blue on the home page and unless I refresh it remains blue. When I refresh it rerenders and the navbar gets its correct colour.
In documentation they wraps component first with redux and then with router
I propose you change your:
export default connect(mapStateToProps)(withRouter(NavBar));
to this:
export default withRouter(connect(mapStateToProps)(NavBar));
The Nativescript Timepicker documentation says I can use both loaded and timeChange events in order to inteact with the dates.
However I need to get the time just when the user press a submit button. Can you give me some guidelines for achieve this? I've using #ViewChild for getting the Element by reference although seems not to be the right way to do it.
You can use #ViewChild to get a reference to your TimePicker and read the current time values. Still, if you prefer, you could also directly use the native loaded event to achieve the same thing.
Example with using a reference from the loaded event
time-picker.component.html
<StackLayout class="home-panel">
<TimePicker #tp (loaded)="onTimePickerLoaded($event)"
[hour]="currentHour" [minute]="currentMinute"
verticalAlignment="center"></TimePicker>
<Button text="Submit" (tap)="onSubmit()"></Button>
</StackLayout>
time-picker.component.ts
import { Component } from "#angular/core";
import { TimePicker } from "tns-core-modules/ui/time-picker";
#Component({
selector: "time-picker",
moduleId: module.id,
templateUrl: "./time-picker.component.html"
})
export class HomeComponent {
currentHour: number = new Date().getHours();
currentMinute: number = new Date().getMinutes();
timePicker: TimePicker;
onTimePickerLoaded(args) {
this.timePicker = args.object as TimePicker;
}
onSubmit(): void {
console.log("Submit was pressed");
console.log(this.timePicker.time);
console.log(this.timePicker.hour);
console.log(this.timePicker.minute);
}
}
Playground demo for the above scenario.
Another possibility is to get the reference via getViewById and with Page DI.
Example for using Page dependency injection.
time-picker.component.html
<StackLayout class="home-panel">
<TimePicker #tp id="my-time-picker" (loaded)="onTimePickerLoaded($event)"
[hour]="currentHour" [minute]="currentMinute"
verticalAlignment="center"></TimePicker>
<Button text="Submit" (tap)="onSubmit()"></Button>
</StackLayout>
time-picker.component.ts
import { Component } from "#angular/core";
import { TimePicker } from "tns-core-modules/ui/time-picker";
import { Page } from "tns-core-modules/ui/page";
#Component({
selector: "Home",
moduleId: module.id,
templateUrl: "./time-picker.component.html",
})
export class HomeComponent {
currentHour: number = new Date().getHours();
currentMinute: number = new Date().getMinutes();
timePicker: TimePicker;
constructor(private _page: Page) {
this._page.on("loaded", () => {
this.timePicker = this._page.getViewById("my-time-picker");
})
}
onSubmit(): void {
console.log("Submit was pressed");
console.log(this.timePicker.time);
console.log(this.timePicker.hour);
console.log(this.timePicker.minute);
}
}
Playground demo for the above example
I am using react native to develop a simple Touchablehighlight element with onpress event. iOS is ok to go but Android takes few seconds to load a function each time. I have looked up few possible solutions such as TouchableWithoutFeedback, TouchableNativeFeedback, etc.
My idea is to click a TouchableHighlight -> call handlePress function -> alert('hello world') under a flatlist
Here is my code.
import React from "react";
import { Image, TouchableHighlight, Platform, TouchableNativeFeedback, View, Text } from "react-native";
import styles from "./Styles";
// Plugin
import FastImage from "react-native-fast-image";
class BacktoTop extends React.Component {
constructor(props) {
super(props);
}
_handlePress = () => {
alert('hello world')
}
render() {
return (
<TouchableHighlight
style={ styles.container }
underlayColor={"#ffffff"}
// onPress={this.props.handlePress }
onPress={this._handlePress }>
<FastImage
source={
(Platform.OS === 'ios') ?
require("../../images/back_to_top.png")
:
{
// 6 months at least 1 view no deletion
uri: 'https://image.ibb.co/grvFS8/back_to_top.png',
priority: FastImage.priority.cacheOnly,
}
}
resizeMode={FastImage.resizeMode.cover}
style={{ width: 35, height: 35 }} />
</TouchableHighlight>
);
}
}
export default BacktoTop;
Thank you so much for your help.
I think the more view components in the upper level to be rendered, the longer time it takes to load.
After I deleted some of my in parent and removed onMomentumScrollEnd the reaction is improved.
Thanks.
Im trying to use Drawer navigation. I have header.js components which has a hamburger icon to open the left navigation menu
//Header.js
import React from 'react';
import { Text, View, Image, TouchableHighlight} from 'react-native';
import { DrawerNavigator } from 'react-navigation';
// Make a component
const Header = (props, {navigate}) => {
const { textStyle, viewStyle, imgstyle } = styles;
return (
<View style={viewStyle}>
<TouchableHighlight onPress={()=> this.props.navigation.navigate('DrawerToggle')}> //here the error is coming
<Image style={{width:40, height:40}}
source={require('./../media/hamburger.png')}
/>
</TouchableHighlight>
<Text style={textStyle}>{props.headerText}</Text>
</View>
);
};
export default Header;
Here is App.js
const MyApp = DrawerNavigator({
Login: {
screen: Login,
},
Signup: {
screen: Signup,
},
});
export default class App extends React.Component {
render() {
return <MyApp />;
}
}
Here is one of the comoponent Login.js
import React, { Component } from 'react';
import {
Text, View, StyleSheet
} from 'react-native';
import Header from './Header';
export default class Login extends Component{
static navigationOptions = {
drawerLabel: 'Login',
};
render(){
return(
<View >
<Header headerText={'Login'}/>
<Text>Login Screen</Text>
</View>
);
}
}
I am not sure what I am missing to fix this. Please check my code.
EDITED:
I tried without "this" to but no luck. I am checking everywhere in the internet but couldn't find the exact solution or I couldn't get a solution to my mind. Can someone who is good with react native respond on this, Please?
The problem is - you use this keyword in a stateless component: this.props.navigation.navigate('DrawerToggle').
Try just props.navigation.navigate('DrawerToggle') since this is not pointing to the Header component instance in your case.
this in a stateless component is "inherited" from the calling scope (since stateless component is an "arrow" function) and likely points to window or global.