PDA

View Full Version : navigation using treelist



kazz
29 Jun 2017, 8:05 AM
im trying to create single page application by modifying reactor-boilerplate(i am new to react and sencha). my layout.js have header, menu sidebar, content of the page(using Switch then inside i palce route), and footer.

the sidebar is tabpanel and inside have treelist. i want to display page for each leaf node
my menu sidebar looks like this :



import React from 'react';
import PropTypes from 'prop-types';
import { Container, TabPanel, TreeList, } from '@extjs/ext-react';
import { Switch, Route, Redirect, withRouter } from 'react-router-dom'


import MenuA from './MenuA';
import MenuB from './MenuB';
import MenuC from './MenuC';
import MenuD from './MenuD';





export default function MenuSidebar({
onItemClick,
selection,
...props
}) {


const storeMenuA = Ext.create('Ext.data.TreeStore', {
rootVisible: true,
root: MenuA
});
const storeMenuB = Ext.create('Ext.data.TreeStore', {
rootVisible: true,
root: MenuB
});
const storeMenuC = Ext.create('Ext.data.TreeStore', {
rootVisible: true,
root: MenuC
});
const storeMenuD = Ext.create('Ext.data.TreeStore', {
rootVisible: true,
root: MenuD
});
return(
<TabPanel
shadow
maxWidth="17%"
tabBar={{ docked: 'bottom', }}
hidden={props.Hidden}
>
<Container iconCls="x-fa fa-database" >
<TreeList
ui='nav'
expanderOnly={false}
expanderFirst={false}
onItemClick={(tree, item) => onItemClick(item.node.getId())}
selection={selection}
store={storeMenuC}
/>
</Container>
<Container iconCls="x-fa fa-exchange" >
<TreeList
expanderOnly={false}
expanderFirst={false}
singleExpand={true}
onItemClick={(tree, item) => onItemClick(item.node.getId())}
selection={selection}
store={storeMenuD}
/>
</Container>
<Container iconCls="x-fa fa-balance-scale" >
<TreeList
expanderOnly={false}
expanderFirst={false}
onItemClick={(tree, item) => onItemClick(item.node.getId())}
selection={selection}
store={storeMenuB}
/>
</Container>

<Container iconCls="x-fa fa-files-o" >
<TreeList
expanderOnly={false}
expanderFirst={false}
onItemClick={(tree, item) => onItemClick(item.node.getId())}
selection={selection}
store={storeMenuA}
/>
</Container>
</TabPanel>
)
}




sample of MenuA files (only leaf node have page/route):





export default {
expanded: true,
text: 'All',
leaf:false,
children: [{
text: 'MenuA',
iconCls: 'x-fa fa-home',
children: [{
text: 'Sub-menu-A-1',
id: '/Sub-menu-A-1',
iconCls: 'x-fa fa-inbox',
leaf: true
}, {
text: 'Sub-menu-A-2',
id: '/Sub-menu-A-2',
iconCls: 'x-fa fa-database',
leaf:true
}]
}, {
text: 'Menu AA',
iconCls: 'x-fa fa-group',
children: [{
text: 'Sub-menu-AA-1',
iconCls: 'x-fa fa-tag',
leaf: true
}, {
text: 'Sub-menu-AA-2',
iconCls: 'x-fa fa-trash',
leaf: true
}, {
text: 'Sub-menu-AA-3',
iconCls: 'x-fa fa-trash',
leaf: true
}]
}, {
text: 'MenuAAA',
iconCls: 'x-fa fa-wrench',
children: [{
text: 'Sub-menu-AAA-1',
iconCls: 'x-fa fa-share-alt',
leaf: true
}, {
text: 'Sub-menu-AAA-2',
iconCls: 'x-fa fa-flag',
leaf: true
}, {
text: 'Sub-menu-AAA-3',
iconCls: 'x-fa fa-signal',
children: [{
text: 'Sub-Sub-menu-AAA-1',
iconCls: 'x-fa fa-share-alt',
leaf: true
}, {
text: 'Sub-Sub-menu-AAA-2',
iconCls: 'x-fa fa-flag',
leaf: true
}, {
text: 'Sub-Sub-menu-AAA-3',
iconCls: 'x-fa fa-signal',
leaf: true
}]
}]
}]
};



will sleep no and check in few hour. thanks for the help.

Mark.Brocato
29 Jun 2017, 8:52 AM
Can you explain what error/problem you're seeing? One problem I see in your code is that the stores are being recreated on each render. I would refactor MenuSidebar as a class instead of a stateless component and create the stores in the constructor or in property initializers.

I took your code and fixed up a few things here:

22d0

kazz
2 Jul 2017, 5:03 PM
sorry for the late replay. your solution works (i forget to show loging on firefox so the console do not show anything) but i have one more question. if i want to make menu using react router is this the right approach ? what should i do? thanks


also i get unreachable code after return statement error on this part of the library.


/**
* Create a function that will throw an error if called (in debug mode) with a message that
* indicates the method has been removed.
* @param {String} suggestion Optional text to include in the message (a workaround perhaps).
* @return {Function} The generated function.
* @private
*/
Ext.deprecated = function(suggestion) {
if (!suggestion) {
suggestion = '';
}
function fail() {
Ext.raise('The method "' + fail.$owner.$className + '.' + fail.$name + '" has been removed. ' + suggestion);
}
return fail;
return Ext.emptyFn;
};

kazz
4 Jul 2017, 2:17 AM
i am trying to create something like this : http://examples.sencha.com/extjs/6.2.0/examples/kitchensink/#tree-list

(http://examples.sencha.com/extjs/6.2.0/examples/kitchensink/#tree-list)
my app.js is like



state = {
hideNav: false,
PageTitle:"Beranda"
}


onNavItemClick = (id) => {

console.log(`nav item ${id} clicked`);

this.setState({
PageTitle: id
});

if(!id.startsWith("ext")){

location.hash = id;

this.setState({
PageTitle: "Beranda"
});
}

}


toggleNav = () => {
this.setState({
hideNav: !this.state.hideNav
});
}




and on render function

<MenuSidebar onItemClick={this.onNavItemClick} hidden={hideNav}/>


<HashRouter>
<switch>
<Route path="/" component={Home} exact/>
<Route path="/DaftarPaketKegiatan" component={PaketKegiatan} />
<Route path="/User" component={User} exact/>
<Route path="/Role" component={Role} exact/>

<Route component={NoMatch}/>
</switch>
</HashRouter>




but thats not working everytime i visit this page :


import React from 'react';
import { Container, TabPanel,FormPanel,FieldSet,TextField,SelectField,ComboBoxField,DatePickerField,TextAreaField,Grid,Panel,Button,Column } from '@extjs/ext-react';

import data from './data'
export default class PaketKegiatan extends React.Component{
/*
state = {
jobs: []
}*/

componentDidMount() {
/*var _this = this;
this.serverRequest =
axios
.get("http://codepen.io/jobs.json")
.then(function(result) {
_this.setState({
jobs: result.data.jobs
});
})*/
}

componentWillUnmount() {
// this.serverRequest.abort();
}

render(){
return(
<TabPanel
shadow
tabBar={{ docked: 'top' }}
>
<Container title="Paket Kegiatan" scrollable={true} >
<FormPanel shadow padding="20">
<FieldSet>
<TextField placeholder="Kode Paket" label="Kode Paket" required/>
<TextField placeholder="Nama Paket" label="Nama Paket" required/>
<SelectField
label="Satuan Kerja"
width="200"
options={[
{ text: '', value: null },
{ text: 'Satker 1', value: 1 },
{ text: 'Satker 2', value: 2 },
{ text: 'Satker 3', value: 3 }
]}
/>
<SelectField
label="Nama PPK"
width="200"
options={[
{ text: '', value: null },
{ text: 'Option 1', value: 1 },
{ text: 'Option 2', value: 2 },
{ text: 'Option 3', value: 3 }
]}
/>
<ComboBoxField
width={200}
label="Penanggung Jawab Pekerjaan"
store={data}
displayField="name"
valueField="abbrev"
queryMode="local"
labelAlign="placeholder"
clearable
/>

<TextField placeholder="Nilai Paket" label="Nilai Paket" required/>
<TextField placeholder="No Kontrak" label="No Kontrak" required/>
<DatePickerField
width={200}
value={new Date()}
destroyPickerOnHide
label="Tanggal Kontrak"
picker={{
yearFrom: 1990
}}
/>
<TextField placeholder="Jenis Paket" label="Jenis Paket" required/>
<TextField placeholder="Durasi Paket" label="Durasi Paket" required/>
<TextField placeholder="Satuan" label="Satuan" required/>
<TextField placeholder="No. SPMK" label="No. SPMK" required/>
<ComboBoxField
width={200}
label="Nama Penyedia Jasa"
store={data}
displayField="name"
valueField="code"
queryMode="local"
labelAlign="placeholder"
clearable
/>
<DatePickerField
width={200}
value={new Date()}
destroyPickerOnHide
label="Waktu Penyelesaian"
picker={{
yearFrom: 1990
}}
/>
</FieldSet>

</FormPanel>
</Container>
<Container title="Detail Paket" >
<TextAreaField
label="Maksud"
maxRows={10}
/>
<TextAreaField
label="Tujuan"

maxRows={10}
/>
<TextAreaField
label="Sasaran"
maxRows={10}
/>
<Grid title="Lingkup Kegiatan" shadow grouped>
</Grid>
<Grid title="Output/Produk Jawab Pekerjaan" shadow grouped>
</Grid>
</Container>
<Container title="Tenaga Ahli" >
<Panel shadow layout={{ type: 'hbox', pack: 'space-between' }} >
<TextField placeholder="Nama" label="Nama" required/>
<TextField placeholder="Pendidikan Terakhir" label="Pendidikan Terakhir" required/>
<TextField placeholder="Kualifikasi" label="Kualifikasi" required/>
<TextField placeholder="Lama Pengalaman" label="Lama Pengalaman" required/>
<TextField placeholder="Sertifikat Keahlian" label="Sertifikat Keahlian" required/>
<Button text="Tambah"></Button>
</Panel>
<Grid shadow grouped>
<Column text="Nama" dataIndex="name" width="150"/>
<Column text="Pendidikan Terakhir" width="150" />
<Column text="Kualifikasi" width="100" />
<Column text="Lama Pengalaman" width="150" />
<Column text="Sertifikat Keahlian" width="150" />
</Grid>
</Container>

<Container title="Tim Teknis" >
<Panel shadow layout={{ type: 'hbox', pack: 'space-between' }} >
<TextField placeholder="No SK Timteknis" label="No SK Timteknis" required/>
<TextField placeholder="Nama Tim Teknis" label="Nama Tim Teknis" required/>
<TextField placeholder="Kategori" label="Kategori" required/>
<TextField placeholder="Posisi" label="Posisi" required/>
<Button text="Tambah"></Button>
</Panel>
<Grid shadow grouped>
<Column text="No SK Timteknis" width="150"/>
<Column text="Nama Tim Teknis" width="150" />
<Column text="Kategori" width="100" />
<Column text="Posisi" width="150" />
</Grid>
</Container>
<Container title="Tahapan" >
<Panel shadow layout={{ type: 'hbox', pack: 'space-between' }} >
<TextField placeholder="Urutan Tahapan" label="Urutan Tahapan" required/>
<TextField placeholder="Tahapan" label="Tahapan" required/>
<Button text="Tambah"></Button>
</Panel>
<Grid shadow grouped>
<Column text="Urutan Tahapan" width="150"/>
<Column text="Tahapan" width="150"/>
</Grid>
</Container>
<Container title="Jadwal" >
<Panel shadow layout={{ type: 'hbox', pack: 'space-between' }} >
<TextField placeholder="Tahapan" label="Tahapan" required/>
<TextField placeholder="Detail Kegiatan/Jadwal" label="Detail Kegiatan/Jadwal" required/>
<DatePickerField
width={200}
value={new Date()}
destroyPickerOnHide
label="Tanggal Mulai"
picker={{
yearFrom: 1990
}}
/>
<DatePickerField
width={200}
value={new Date()}
destroyPickerOnHide
label="Tanggal Selesai"
picker={{
yearFrom: 1990
}}
/>
<Button text="Tambah"></Button>
</Panel>
<Grid shadow grouped>
<Column text="Tahapan" width="150"/>
<Column text="Detail Kegiatan/Jadwal" width="150" />
<Column text="Tanggal Mulai" width="150" />
<Column text="Tanggal Selesai" width="150" />
</Grid>
</Container>
<Container title="Rencana Penyerapan" >
<Panel shadow layout={{ type: 'hbox', pack: 'space-between' }} >
<TextField placeholder="Rencana Penyerapan" label="Rencana Penyerapan" required/>
<DatePickerField
width={200}
value={new Date()}
destroyPickerOnHide
label="Tanggal"
picker={{
yearFrom: 1990
}}
/>
<TextField placeholder="Persentase" label="Persentase" required/>
<TextField placeholder="Dokumen Pendukung" label="Dokumen Pendukung" required/>
<Button text="Tambah"></Button>
</Panel>
<Grid shadow grouped>
<Column text="Rencana Penyerapan" width="150"/>
<Column text="Tanggal" width="150" />
<Column text="Presentase" width="150" />
<Column text="Dokumen Pendukung" width="150" />
</Grid>

</Container>
</TabPanel>

);
}
}

Mark.Brocato
5 Jul 2017, 6:36 AM
Can you be more specific about what's not working? Are you getting an error message? Can you share a screenshot or a gif?

kazz
6 Jul 2017, 9:57 PM
Can you be more specific about what's not working? Are you getting an error message? Can you share a screenshot or a gif?
i want to make menu using tree list. the error that iam seeing is everytime i click link the whole page is reloaded instead part of the page.


i am using browserRouter, not hashRouter (like my prev post)
my onNavItemClick fungtion :



onNavItemClick = (id) => {
console.log(`nav item ${id} clicked`);

if(!id.startsWith("ext")){
location.pathname = id;
}


}


what i must put on onNavItemClick function so the link is working correctly. sorry i don't know how to post gif. here output of my console if that help:
56577

Mark.Brocato
7 Jul 2017, 5:24 AM
You should use react router's history.push method to change the location path:



import { withRouter } from 'react-router-dom';
import React from 'react';


class PaketKegiatan extends React.Component {


...


onNavItemClick = (id) => {
if(!id.startsWith("ext")) {
this.props.history.push(id); // this.props.history is provided by withRouter
}
}


}


export default withRouter(PaketKegiatan);