get active tab from Closable TabPanel in extReact sencha component - sencha-touch

I'm making Closable TabPanel and at the moment when I click on the certain tab I will switch to the Panel of that's tab. What Panel's tab I click, that Panel opens. That's great.
but now I want to have a carousel button on the side, to list next, next, next Panel.
Which means I need to know on what panel I am at the moment (what panel is active now)? And How to tell take next panel in the row ( setPanel(activeId+1) ) ?
For now, I'm getting a list of all existing PANELS and I extract all their IDs: [45,46,47,48,49]. I'm getting it form DataBase, but I don't know how to get currently Active panel and how to say go to next!?
Any ideas?

use property: activeItem={2}
for example: <TabPanel activeItem={this.state.componentNumber} border={false} ...> </TabPanel>
App.js
import React, { Component } from 'react';
import { Button } from '#extjs/ext-react';
import ClosableComponent from './ClosableComponent';
class App extends Component {
constructor() {
super();
this.state = {
componentNumber: 2,
};
}
switchFunctionLeft = () => {
if(this.state.componentNumber === 0){
this.setState({ componentNumber: 2 })
}else{
this.setState({ componentNumber: this.state.componentNumber - 1 })
}
}
switchFunctionRight = () => {
if(this.state.componentNumber === 2){
this.setState({ componentNumber: 0 })
}else{
this.setState({ componentNumber: this.state.componentNumber + 1 })
}
}
render() {
return (
<div className="App">
<div >
<ClosableComponent componentNumber={this.state.componentNumber} />
<Button text="switch to left" handler={this.switchFunctionLeft} />
<Button text="switch to right" handler={this.switchFunctionRight}/>
</div>
</div>
);
}
}
export default App;
ClosableComponent.js
import React, {
Component
} from 'react';
import {
TabPanel,
Container,
Toolbar,
Button
} from '#extjs/ext-react';
class ClosableComponent extends Component {
nextKey = 0;
constructor() {
super();
this.state = {
type: "No",
switch: "",
tabs: [
this.nextKey++,
this.nextKey++,
this.nextKey++
]
};
}
onCloseTab = tab => {
const tabs = this.state.tabs.filter(t => t !== tab);
this.setState({
tabs
})
}
addTab = () => {
const key = this.nextKey++;
const tabs = [...this.state.tabs, key];
this.setState({tabs})
this.tabPanel.setActiveItem(tabs.indexOf(2))
return false;
}
render() {
const { tabs } = this.state;
return (
<div>
<Container layout="fit" padding = {10}>
<TabPanel
ref = {tp => this.tabPanel = tp}
_reactorIgnoreOrder
shadow
style={{ backgroundColor: 'white', "height": "200px"}}
activeItem={this.props.componentNumber}
tabBar={{
height: 48,
layout: {
pack: 'left'
},
style: {
paddingRight: '52px'
}
}}
>
{ tabs.map(key => (
<Container
title = {`Tab ${key}`}
tab = {{ flex: 1, maxWidth: 150 }}
key = {key}
layout = "center"
closable
onDestroy = {this.onCloseTab.bind(this, key)}
>
<div style = {{ whiteSpace: 'nowrap' }}>Tab {key} Content</div>
</Container>
))}
</TabPanel>
<Button
top={18}
right={20}
iconCls="x-fa fa-plus"
handler={this.addTab}
ui="alt round"
tooltip="New Tab"
/>
</Container>
</div>
);
}
}
export default ClosableComponent;

Related

Error: Text strings must be rendered within a <Text> component, occurs in android but works fine on web

My code is working fine on web browser. But when I run it on the cell phone, it shows the error as shown in image. The error is pointed towards the div tags. Got stuck on the error for couple of hours. Also wrapped the div tags with and but none working for me. Any help would be highly appreciated. Here is the code:
import React, { Component } from 'react';
import paginate from 'paginate-array';
import { View,Text,TouchableOpacity,StyleSheet,FlatList,Platform,ActivityIndicator} from 'react-native';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
todos: [],
size: 5,
page: 1,
currPage: null
}
this.previousPage = this.previousPage.bind(this);
this.nextPage = this.nextPage.bind(this);
this.handleChange = this.handleChange.bind(this);
}
componentDidMount() {
fetch(`https://jsonplaceholder.typicode.com/todos`)
.then(response => response.json())
.then(todos => {
const { page, size } = this.state;
const currPage = paginate(todos, page, size);
this.setState({
...this.state,
todos,
currPage
});
});
}
previousPage() {
const { currPage, page, size, todos } = this.state;
if (page > 1) {
const newPage = page - 1;
const newCurrPage = paginate(todos, newPage, size);
this.setState({
...this.state,
page: newPage,
currPage: newCurrPage
});
}
}
nextPage() {
const { currPage, page, size, todos } = this.state;
if (page < currPage.totalPages) {
const newPage = page + 1;
const newCurrPage = paginate(todos, newPage, size);
this.setState({ ...this.state, page: newPage, currPage: newCurrPage });
}
}
handleChange(e) {
const { value } = e.target;
const { todos, page } = this.state;
const newSize = +value;
const newPage = 1;
const newCurrPage = paginate(todos, newPage, newSize);
this.setState({
...this.state,
size: newSize,
page: newPage,
currPage: newCurrPage
});
}
render() {
const { page, size, currPage } = this.state;
return (
<div>
<div>page: {page}</div>
<div>size: {size}</div>
<div>
<label for="size">Size</label>
<select name="size" id="size" onChange={this.handleChange}>
<option value="5">5</option>
<option value="10">10</option>
<option value="25">25</option>
</select>
</div>
{currPage &&
<ul>
{currPage.data.map(todo => <li key={todo.id}>{todo.title}</li>)}
</ul>
}
<button onClick={this.previousPage}>Previous Page</button>
<button onClick={this.nextPage}>Next Page</button>
</div>
)
}
}
export default TodoList;
What I came to know is you want an infinite list, and also you are going towards wrong direction. You are using react instead of react-native. Try using this:
import React, {Component} from 'react';
import {View, Text, FlatList, Image} from 'react-native';
import {Card} from 'react-native-elements';
import axios from 'axios';
class Users extends Component {
constructor(props) {
super(props);
this.state = {
users: [],
page: 1,
error: null,
};
}
componentDidMount() {
this.fetchUsers(this.state.page);
}
fetchMoreUsers = () => {
this.setState(
prevState => ({
page: prevState.page + 100,
}),
() => {
this.fetchUsers();
},
);
};
fetchUsers = () => {
const {page} = this.state;
axios
.get(`https://api.github.com/users?since=${page}&per_page=10`)
.then(response => {
this.setState({
users: this.state.users.concat(response.data),
});
})
.catch(error => {
this.setState({error: error});
});
};
render() {
return (
<FlatList
contentContainerStyle={{
backgroundColor: '#FBFBF8',
alignItems: 'center',
justifyContent: 'center',
marginTop: 15,
}}
data={this.state.users}
keyExtractor={user => user.id.toString()}
onEndReached={this.fetchMoreUsers}
onEndReachedThreshold={0.5}
initialNumToRender={10}
renderItem={({item}) => (
<View
style={{
marginTop: 10,
}}>
<Card>
<Image
style={{width: 200, height: 100}}
source={{uri: item.avatar_url}}
/>
<Text>{item.login}</Text>
</Card>
</View>
)}
/>
);
}
}
export default Users;

How to call function in map loop (react native)?

This is my code. I am not sure what error exists.
When I click the image button, it calls proper function exactly.
If I click the first button, it calls toggleBooks() function correctly.
Then in that function, I want to use vidMute state value.
So I tried console.log('Video toggle', this.state.vidMute); then it gives me an error like the following image.
But if I print console.log('Video toggle'), then it works well.
How to use state value in that function?
export default class Video extends Component {
constructor(props) {
super(props)
this.state = {
vidMute: false,
audioShow: false,
callShow: false,
btn: [
{ func: this.toggleAudio, url: magic, de_url: de_magic },
{ func: this.endCall, url: endcall, de_url: de_endcall },
{ func: this.toggleBooks, url: camerarotate, de_url: de_camerarotate },
],
};
this.toggleAudio = this.toggleAudio.bind(this)
this.endCall = this.endCall.bind(this)
this.toggleBooks = this.toggleBooks.bind(this)
}
toggleBooks() {
console.log('Video toggle', this.state.vidMute);
}
endCall() {
console.log('Call toggle', this.state.audioShow);
}
toggleAudio() {
console.log('Audio toggle', this.state.callShow);
}
render() {
return (
<View>
{
this.state.btn.map((item, index) => (
<TouchableOpacity key={index} style={styles.iconStyle} activeOpacity={0.4} onPress={item.func}>
<Image source={this.state.lockState ? item.de_url : item.url} style={{ width: 70, height: 70 }} />
</TouchableOpacity>
))
}
</View>
)
}
}
this refers to the context of your function and not the context of your component. You can try to bind your method like this :
this.myMethod = this.myMethod.bind(this);
in your constructor.
Or use the fat arrow pattern (Highly recommanded) which automatically includes the binding to your component's context.
Here is a binding example on stackblitz
Here is the code :
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
class App extends Component {
constructor() {
super();
this.state = {
name: 'React',
items:[
{name:"item 1", func: () => this.test()},
{name:"item 2", func: () => this.test2()}
]
};
this.test = this.test.bind(this);
}
test() {
console.log('Hi', this.state.name);
}
test2() {
console.log('Hello', this.state.name); // Note this is not binded
}
render() {
return (
<div>
<Hello name={this.state.name} />
<p onClick={this.test}>
Start editing to see some magic happen :)
</p>
<div>
{
this.state.items.map(item => <div onClick={() => item.func()}>{item.name}</div>)
}
</div>
</div>
);
}
}
render(<App />, document.getElementById('root'));

Resize feature seems to be incompatible with external drag-and-drop

First of all, I would like to express my gratitude for this repo: https://github.com/Tim1023/react-scheduler-firebase without which I would not be able to implement external drag-and-drop for react-big-calendar.
I have spent an entire week trying to play with this stuff, but resize feature (stretching the event up and down) just won't work for it. I guess the problem is with css ?
I have tried to upgrade the react-big-calendar's version from 0.19 to 0.20, and situation is the opposite - resize works perfectly, but external DnD no longer works (namely, when dragging an external object on the calendar, drop mode does not get activated)
There's an open issue regarding this, but looks like it remains unhandled up to now.
The latest version of RBC does include external drag and drop. Although the documentation site has not yet been updated, cloning the repo and running the 'examples' will show a working demo of this functionality. Here is the source for that demo:
import React from 'react'
import events from '../events'
import { Calendar, Views } from 'react-big-calendar'
import withDragAndDrop from 'react-big-calendar/lib/addons/dragAndDrop'
import Layout from 'react-tackle-box/Layout'
import Card from '../Card'
import 'react-big-calendar/lib/addons/dragAndDrop/styles.scss'
const DragAndDropCalendar = withDragAndDrop(Calendar)
const formatName = (name, count) => `${name} ID ${count}`
class Dnd extends React.Component {
constructor(props) {
super(props)
this.state = {
events: events,
draggedEvent: null,
counters: {
item1: 0,
item2: 0,
},
displayDragItemInCell: true,
}
}
handleDragStart = event => {
this.setState({ draggedEvent: event })
}
handleDisplayDragItemInCell = () => {
this.setState({
displayDragItemInCell: !this.state.displayDragItemInCell,
})
}
dragFromOutsideItem = () => {
return this.state.draggedEvent
}
customOnDragOver = event => {
// check for undroppable is specific to this example
// and not part of API. This just demonstrates that
// onDragOver can optionally be passed to conditionally
// allow draggable items to be dropped on cal, based on
// whether event.preventDefault is called
if (this.state.draggedEvent !== 'undroppable') {
console.log('preventDefault')
event.preventDefault()
}
}
onDropFromOutside = ({ start, end, allDay }) => {
const { draggedEvent, counters } = this.state
const event = {
title: formatName(draggedEvent.name, counters[draggedEvent.name]),
start,
end,
isAllDay: allDay,
}
const updatedCounters = {
...counters,
[draggedEvent.name]: counters[draggedEvent.name] + 1,
}
this.setState({ draggedEvent: null, counters: updatedCounters })
this.newEvent(event)
}
moveEvent = ({ event, start, end, isAllDay: droppedOnAllDaySlot }) => {
const { events } = this.state
const idx = events.indexOf(event)
let allDay = event.allDay
if (!event.allDay && droppedOnAllDaySlot) {
allDay = true
} else if (event.allDay && !droppedOnAllDaySlot) {
allDay = false
}
const updatedEvent = { ...event, start, end, allDay }
const nextEvents = [...events]
nextEvents.splice(idx, 1, updatedEvent)
this.setState({
events: nextEvents,
})
// alert(`${event.title} was dropped onto ${updatedEvent.start}`)
}
resizeEvent = ({ event, start, end }) => {
const { events } = this.state
const nextEvents = events.map(existingEvent => {
return existingEvent.id == event.id
? { ...existingEvent, start, end }
: existingEvent
})
this.setState({
events: nextEvents,
})
//alert(`${event.title} was resized to ${start}-${end}`)
}
newEvent = event => {
let idList = this.state.events.map(a => a.id)
let newId = Math.max(...idList) + 1
let hour = {
id: newId,
title: event.title,
allDay: event.isAllDay,
start: event.start,
end: event.end,
}
this.setState({
events: this.state.events.concat([hour]),
})
}
render() {
return (
<div>
<Card className="examples--header" style={{ display: 'flex' }}>
<div
style={{
display: 'flex',
flex: 1,
justifyContent: 'center',
flexWrap: 'wrap',
}}
>
<h4 style={{ color: 'gray', width: '100%' }}>
Outside Drag Sources
</h4>
{Object.entries(this.state.counters).map(([name, count]) => (
<div
style={{
border: '2px solid gray',
borderRadius: '4px',
width: '100px',
margin: '10px',
}}
draggable="true"
key={name}
onDragStart={() =>
this.handleDragStart({ title: formatName(name, count), name })
}
>
{formatName(name, count)}
</div>
))}
<div
style={{
border: '2px solid gray',
borderRadius: '4px',
width: '100px',
margin: '10px',
}}
draggable="true"
key={name}
onDragStart={() => this.handleDragStart('undroppable')}
>
Draggable but not for calendar.
</div>
</div>
<div>
<label>
<input
style={{ marginRight: 5 }}
type="checkbox"
checked={this.state.displayDragItemInCell}
onChange={this.handleDisplayDragItemInCell}
/>
Display dragged item in cell while dragging over
</label>
</div>
</Card>
<DragAndDropCalendar
selectable
localizer={this.props.localizer}
events={this.state.events}
onEventDrop={this.moveEvent}
dragFromOutsideItem={
this.state.displayDragItemInCell ? this.dragFromOutsideItem : null
}
onDropFromOutside={this.onDropFromOutside}
onDragOver={this.customOnDragOver}
resizable
onEventResize={this.resizeEvent}
onSelectSlot={this.newEvent}
onD
defaultView={Views.MONTH}
defaultDate={new Date(2015, 3, 12)}
/>
</div>
)
}
}
export default Dnd

ReactNative and NativeBase Radio

I've tried to change the radio value in ReactNative App with NativeBase template. I want to get or set value from the radio after click it, exactly checked or not. But couldn't find a way to get or set value to it. Even the radio button never changed on the screen after click. The codes are like as below:
import React, { Component } from 'react';
import { TouchableOpacity, Image, View } from 'react-native';
import { connect } from 'react-redux';
import { actions } from 'react-native-navigation-redux-helpers';
import {
Container,
Header,
Title,
Content,
Text,
Button,
Icon,
InputGroup,
Input,
List,
ListItem,
Radio, } from 'native-base';
import { openDrawer } from '../../actions/drawer';
import { Col, Row, Grid } from 'react-native-easy-grid';
import styles from './styles';
import dimension from './global';
import Swiper from 'react-native-swiper';
const imgBoy = require('../../../images/icon_boy.png');
const imgGirl = require('../../../images/icon_girl.png');
const {
popRoute,
} = actions;
class SessionPage extends Component {
static propTypes = {
name: React.PropTypes.string,
index: React.PropTypes.number,
list: React.PropTypes.arrayOf(React.PropTypes.string),
openDrawer: React.PropTypes.func,
popRoute: React.PropTypes.func,
navigation: React.PropTypes.shape({
key: React.PropTypes.string,
}),
}
popRoute() {
this.props.popRoute(this.props.navigation.key);
}
constructor(props) {
super(props);
// console.log(this.props.navigation);
this.state = {
sliderCount : parseInt(this.props.navigation.behavior.length / 5) + 1,
sliderArray : [],
selected : false,
}
this.getSliderArray();
console.log(this.state);
}
getSliderArray() {
for (var i = 0; i < this.state.sliderCount; i++) {
var childArray = [];
for (var j = i * 5; j < 5 * (i + 1); j++) {
if (this.props.navigation.behavior[j] != null){
var unit = this.props.navigation.behavior[j];
unit.selected = true;
childArray.push(unit);
}
}
this.state.sliderArray.push({
index : i,
behaviors : childArray
})
}
}
selectRadio(i, j){
this.state.sliderArray[i].behaviors[j].selected = true;
}
render() {
const { props: { name, index, list } } = this;
return (
<Container style={styles.container}>
<Swiper style={styles.wrapper}
height={dimension.Height - 400}
width={dimension.Width - 40}
showsButtons={false}
showsPagination={true}>
{this.state.sliderArray.map((item, i) =>
<View style={styles.slide1} key={i}>
{item.behaviors.map((subitem, j) =>
<ListItem key={i + "-" + j} style={styles.cardradio}>
<Radio selected={this.state.sliderArray[i].behaviors[j].selected} onPress={() => this.selectRadio(i, j)} />
<Text>{subitem.behaviorName}</Text>
</ListItem>
)}
</View>
)}
</Swiper>
</Content>
</Container>
);
}
}
function bindAction(dispatch) {
return {
openDrawer: () => dispatch(openDrawer()),
popRoute: key => dispatch(popRoute(key)),
};
}
const mapStateToProps = state => ({
navigation: state.cardNavigation,
name: state.user.name,
index: state.list.selectedIndex,
list: state.list.list,
});
export default connect(mapStateToProps, bindAction)(SessionPage);
selectRadio(i, j){
this.state.sliderArray[i].behaviors[j].selected = true; <== This is the problem
}
When you call this.state = something after the component has mounted, it doesn't trigger update method of component life cycle. Hence view will not be updated.
You should be using this.setState() to update your views
this.setState({
slider = something
})
For more info, refer docs
this.setState() is an async method. After you make changes in getSliderArray(), it may not be reflected in immediate console.log
this.getSliderArray();
console.log(this.state);
You can pass callback to this.setState() to perform any action only after state is changed
this.setState({
// new values
}, function() {
// Will be called only after switching to new state
})

Native-Base not loading elements

I am using native-base version 2.0.2, react-native version 0.40.0.
I am following a tutorial to make a GithHub Repo Search using native-base & integrate it with my functionalities to make something different, but all of the components are not properly loaded.
The Header & Footer example from the docs worked fine, but when I add things like searchbar rounded property or the icon classes, it does not get reflected.
When I add the button component I get the following error.
The Code in question is
var constants = require("../constants")
var React = require('react');
var ReactNative = require('react-native');
var t = require('tcomb-form-native');
var authenticate = require("../services/authenticate")
import { Container, Header, Title, Content, Footer, FooterTab, Button, Left, Right, Body,Picker,InputGroup,Icon,Input,Item } from 'native-base';
var {
AppRegistry,
AsyncStorage,
StyleSheet,
Text,
View,
TouchableHighlight,
Alert,
ListView,
Image,
} = ReactNative;
var Form = t.form.Form;
var getFeatured = require("../services/get_featured");
var getCategory = require("../services/get_categories");
var search = require("../services/search");
var Query;
const options = {
fields: {
category: {
order: 'asc',
nullOption: {value: '', text: 'Anything'}
}
}
}
class SplashPage extends React.Component{
constructor() {
super();
this.set_initial_state()
//this.set_categories();
//this.get_featured();
}
set_initial_state(){
this.state ={
hasResult: false,
hasCategory:false,
noResult: false,
isLoading: true,
isLoadingCat:true,
searchResult:false,
categories : [],
searchText:"",
searchCat:"",
filterCat:"",
articles:[],
}
}
set_categories() {
var par = this;
getCategory().then(function(catData){
par.setState({
isLoadingCat:false,
hasCategory:true,
categories:catData,
});
console.error("till here");
});
}
get_categories(){
const cats = this.state.categories;
const CatItems = cats.map((cat,i)=>{
return (
<Picker.item key={i} label={cat} value={cat} />
);
});
return CatItems;
}
openRecipe(data){
this.props.navigator.push({
id: 'RecipePage',
name: 'Recipe',
recipe_id:data.id,
});
}
get_featured(){
var par = this;
getFeatured().then(function(articles){
par.setState(
{
articles:articles,
hasResult: true,
isLoading:false,
searchResult:false,
}
)
}).catch(function(error) {
console.error(error);
});
}
perform_search(){
var value = this.state.searchText;
var par = this;
if(value){
par.setState(
{
hasResult: false,
isLoading:true,
}
)
var category = value.category;
var ingredient = value.ingredient.toString().split(',').join(' ');
search(ingredient,category).then((articles) => {
par.setState(
{
articles:articles,
hasResult: true,
isLoading:false,
searchResult:true
}
)
}).catch(function(error) {
console.error(error);
});
}
}
render() {
return (
<Header searchBar rounded>
<InputGroup>
<Icon name="ios-search" />
<Input placeholder="Search" value={this.state.searchText} onChangeText={(text) => this.setState({searchText:text})} onSubmitEditing={()=>this.search()}/>
<Picker
iosHeader="Select one"
mode="dropdown"
selectedValue={this.state.searchCat}
onValueChange={(cat) => this.setState({searchCat:cat})}>
<Item label="Cats" value="key0" />
<Item label="Cats2" value="key02" />
</Picker>
</InputGroup>
<Button transparent onPress={()=>this.search()}>Go</Button>
</Header>
);
}
}
module.exports = SplashPage;
I checked the dependencies and everything is installed.
I think you should wrap your code in
<Container>
<Content>
// your code
<Button>
<Text>Click Me! </Text>
</Button>
</Content>
</Container>
there's something wrong i think in your Button on onPress.
your code is onPress={()=>this.search()}
but i don't see search() method, i just find perform_search() method
if your problem came after you add <Button> tag, you can change this one :
<Button transparent onPress={()=>this.search()}>Go</Button>
to this one :
<Button transparent onPress={()=>this.perform_search()}><Text>Go</Text></Button>
and also this one : onSubmitEditing={()=>this.search()}
to this one : onSubmitEditing={()=>this.perform_search()}
and don't forget to import Text in native-base, hope can solve your problem :)