With react-native-navigation v1 you can set up a drawer like this:
drawer: {
left: {
screen: 'ScreenName'
}
}
In docs of react-native-navigation they mention that drawer is still supported,
but there in no example of its usage. I tried with same way as in v1, but it didn't work. Is there anyone who has achieved it somehow?
In RNN V2 and up you can add Drawer with simply using sideMenu instead of old drawer option Ex :
Navigation.events().registerAppLaunchedListener(() => {
Navigation.setRoot({
root: {
sideMenu: {
id: "sideMenu",
left: {
component: {
id: "Drawer",
name: "navigation.Drawer"
}
},
center: {
stack: {
id: "AppRoot",
children: [{
component: {
id: "App",
name: "navigation.AppScreen"
}
}]
}
}
}
}
});
}
Take a look at this and navigate to sideMenu
and in order to close the drawer use Navigation.mergeOptions and pass visible false like this
<Button onPress={this.hideSideMenu}/>
hideSideMenu() {
Navigation.mergeOptions(this.props.componentId, {
sideMenu: {
left: {
visible: false
}
}
});
}
Related
I am using react-native-navigation v2 from Wix, trying to push a screen to an existing stack. Here is my push code:
Navigation.push(this.props.componentId, {
component: {
name: 'chapel.search'
}
})
And my options object
static options (passProps) {
console.log('Firing static method')
return {
component: {
name: 'chapel.search',
topBar: {
visible: true,
leftButtons: [
{
id: 'back',
testID: 'back',
icon: require('../../Images/back.png')
}
],
title: {
component: {
name: 'chapel.navtitle',
alignment: 'center',
passProps: { text: 'Search' }
}
},
rightButtons: []
}
}
}
}
I never see the log statement and the topbar options do not change. Should they?
When I use Navigation.mergeOptions with the above options object in the constructor of my target screen, the options appear, so this is what I am using for now.
Using android, have not tested with iOS as yet. Will update when I do.
I'm originating static options like this in my component:
static get options() {
return {
...
}
}
And when i push from another screen and want to override some defaults, i do it like below:
Navigation.push(this.props.componentId, {
component: {
name: 'chapel.search',
passProps: {
myProp: myprop1
},
options: {
topBar: {
title: {
text: newTitleOverridingStaticOne
}
}
}
}
});
I don't know if static options (passProps){...} is valid, but you can try like i show above to check if it is resolved
While navigating to different screens from side menu, I hid the side menu using following code:
Navigation.mergeOptions('Drawer', {
sideMenu: {
left: {
visible: false,
}
}
});
The problem using this approach was change in behavior of swipe gesture. While using gesture to open the menu, it would appear for a instance and close itself. And swipe gesture would only work properly after your click the menu button.
closeSideMenu = ( ) => {
/*For android devices*/
if (Platform.OS === 'android') {
/*disable swipe gesture*/
Navigation.mergeOptions("navigation.playground.menu", {
sideMenu: {
left: {
enabled: false,
},
},
});
/*enable swipe gesture*/
Navigation.mergeOptions("navigation.playground.menu", {
sideMenu: {
left: {
enabled: true,
},
},
});
} else {
/*for iOs devices*/
Navigation.mergeOptions("navigation.playground.menu", {
sideMenu: {
left: {
visible: false,
},
},
});
}
};
I'm currently trying to upgrade to react-native-navigation V2 from V1 and got stuck trying to find a way to toggle side menus on top bar button press.
My app starts with
Navigation.setRoot({
root: {
sideMenu: {
left: {
component: {
name: 'testApp.SideDrawer',
passProps: {
text: 'This is a left side menu screen'
}
}
},
center: {
bottomTabs: {
...
}
},
},
},
});
Is there a way to do it in current version?
Turned out you can't use this.props.navigator.toggleDrawer in V2 and should use Navigator.mergeOptions instead to change drawer visibility.
In my case:
1) First assign an Id to the drawer (id: leftSideDrawer)
Navigation.setRoot({
root: {
sideMenu: {
left: {
component: {
name: 'testApp.SideDrawer',
id: 'leftSideDrawer'
}
},
center: {
bottomTabs: {
...
}
},
},
},
});
2) Use it in to change drawer visibility
Navigation.mergeOptions('leftSideDrawer', {
sideMenu: {
left: {
visible: true
}
}
});
You can set a boolean in your component to identify the current state of the side drawer screen and then you can use that boolean to set the visibility of the drawer with mergeOptions. Basically toggle! Below is the snippet to achieve this.
constructor(props) {
super(props);
this.isSideDrawerVisible = false;
Navigation.events().bindComponent(this);
}
navigationButtonPressed({ buttonId }) {
if (buttonId === "openSideDrawer") {
(!this.isSideDrawerVisible) ? this.isSideDrawerVisible = true : this.isSideDrawerVisible = false
Navigation.mergeOptions(this.props.componentId, {
sideMenu: {
left: {
visible: this.isSideDrawerVisible,
}
}
});
}
}
I try to update label on menu item when I click this menu item. It should works like click->'show' label, click->'hide' label. This is my code:
const template = [{
label: 'Menu',
submenu: [{
label: 'Search',
click() {
win.webContents.executeJavaScript("showSearch()"); // it run function changeSearch() in main.js
}
},
{
label: 'Resetuj',
click() {
win.loadURL(`file://${__dirname}/index.html?del=1`);
}
},
{
label: 'Quit',
accelerator: 'Q+CmdOrCtrl+Q',
click() {
win.loadURL(`file://${__dirname}/index.html?logout=1&close=1`);
}
}]
}];
changeSearch() I tried something like this:
Menu.items[0].submenu.items[0].label = "Changed label";
I think what you are looking for is something like this:
function addMenuItems(items, position) {
const updateSearchItems = [{
label: 'newOptionDisabled',
enabled: false,
}, {
label: 'newOptionWithAction',
enabled: true,
key: 'newOptionWIthAction',
}, {
label: 'Do some stuff',
visible: false,
key: 'doSomeStuff',
click: () => {
// stuff
},
}];
items.splice.apply(items, [position, 0].concat(updateSearchItems));
}
By defining your menu items as an object that you can reference you can always modify the object later. In my example I use a addMenuItems function that enables me to specify where I want to insert these items within the existing object.
I did this to change/modify my menu item dynamically:
const menuTemplate = [{
label: 'Options',
submenu: [
{
label: 'Hide',
click() {
changeLabel('Show'); // Put logic here
}
}
]
}];
function changeLabel(label) {
menuTemplate[0].submenu[0].label = label;
// Rebuild menu
const menu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menu);
}
This code is not tested!
I have an Angular Formly-based form in my Angular-SPA. In one of the fields the user can enter data with the help of a physical barcode-scanner. The scanner enters the numbers from the barcode followed by 'enter' (keycode: 13).
When the 'enter' is entered, the form should preform an action (not a form submit-action, but an internal search to make sure the entered number doesn't already exists in the system), then the user can proceed to fill out the form.
In vanilla javascript, its possible to do this by a simple onKeypress-event:
function checkInput(event) {
if (event.keyCode == 13) {
console.log("Preforming search");
}
}
<input type="text" onKeypress="checkInput(event)">
In Formly however, it's possible to add a property 'onKeypress', but it doesn't seem to pass the same event as vanilla javascript. This is some of my Angular Formly code:
templateOptions : {
placeholder: "ISBN",
onKeypress: function(model, options, _this, event) {
console.log(model);
console.log(options);
console.log(_this);
console.log(event);
}
}
When I run this code, the event-object is 'undefined', instead of being the same event as in vanilla javascript.
Is there any way to access the actual event in the onKeypress-property of Angular Formly-forms?
Cheers!
Update
Found a solution! I was trying to do this to a custom type, which is then inherited to the actual input-element.
Seems like Formly doesn't allow inheritance of the onKeypress-property. I moved the onKeypress-property to the actual element, and I was able to solve the problem.
It's a bit unfortunate that this can not be inherited, but have to be defined for each element instead.
My problem (simplified) :
formlyConfig.setType({
name: 'multiInput',
templateUrl: 'app/editor/multiInput.html',
defaultOptions: {
wrapper: ['bootstrapLabel', 'boostrapHasError'],
templateOptions: {
inputOptions: {
type: 'input',
wrapper: null
},
onKeypress: function(model, options, _this, event) {
// DO SEARCH (NOT WORKING)
}
}
}
}
// --------------------------- //
{
className: 'col-xs-10',
type: "multiInput",
key: "isbns",
templateOptions: {
label: 'ISBN',
inputOptions: {
templateOptions: {
required: true,
disabled: true,
placeholder: 'ISBN'
}
},
key: "isbn",
}
}
}
My solution:
formlyConfig.setType({
name: 'multiInput',
templateUrl: 'app/editor/multiInput.html',
defaultOptions: {
wrapper: ['bootstrapLabel', 'boostrapHasError'],
templateOptions: {
inputOptions: {
type: 'input',
wrapper: null
}
}
}
}
// --------------- //
{
className: 'col-xs-10',
type: "multiInput",
key: "isbns",
templateOptions: {
label: 'ISBN',
inputOptions: {
templateOptions: {
required: true,
disabled: true,
placeholder: 'ISBN',
onKeypress: function(model, options, _this, event) {
// DO SEARCH (WORKING!)
}
}
},
key: "isbn"
}
}
}
It's not the best solution, I want more inputs to have the onKeypress-event. But it looks like I might have to add them separately.