iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 13
0
Modern Web

React.js & Laravel 30天訓練系列 第 13

【Day 13】Loading Left Drawer Menu Data List

  • 分享至 

  • twitterImage
  •  

回來面對囉 雖然說是面對 不過是應該說 把之前做的完整說一下

OK 講一下大概要做什麼

  1. 左側的選單要能夠讀取出 現在登入的使用者名稱
  2. 左側的選單要能夠讀取出 現在的公司名稱
  3. 讀取使用者能夠進入的公司總清單
  4. 讀取使用者能夠進入的討論組清單
  5. 讀取公司內的成員資料

我們先看一下我最後的成果樣子
這個是外側的選單
https://ithelp.ithome.com.tw/upload/images/20180103/20107767CaG109B3Ow.png

再來是打開可以選擇的公司名單
https://ithelp.ithome.com.tw/upload/images/20180103/20107767y7HZS0Bjsm.png

簡單說 這裡考慮到幾項事情

  1. 你要先拿到所有的成員名單,因為到時候我們就可以直接用UserID 去對應出我們要的登入者名稱
export const GetAllCompMember = (_compid, _userid, _token) => {
	var formData = new FormData();
	formData.append("token", _token);
	formData.append("CompID", _compid);

	return (dispatch) => {
		fetch("http://xx.xxx.xxx/user/get_comp_all_member", {
				method: "POST",
				body: formData
			})
			.then(function(response) {
				return response.json();
			})
			.then(function(jsonData) {
				let _currentUser = jsonData.data.filter(function(_ele) {
					return _ele.UserID == _userid;
				});
				dispatch({
					type: Insert_All_Comp_Member,
					payload: {
						AllCompUser: jsonData.data
					}
				});
				dispatch({
					type: Update_Current_User_Name,
					payload: {
						CurrentUser: _currentUser[0]
					}
				});
			})
			.catch(function(e) {
				console.log(e);
			})
	}
};

這一段主要就是拉回所有成員 並在同時更新 我目前這個登入者的名稱 讓他顯示出來

看完 Action 接下來看一下 container 連接什麼東西

export default connect(
	// 從這裡把State的狀態值抽出來,然後component那邊就可以用this.props.Email 把它放在function 當成參數來傳
	(state) => ({
		Token: state.getIn(['InitReducer', 'Token']),
		CompID: state.getIn(['InitReducer', 'CurrentUser', 'CompID']),
		UserID: state.getIn(['InitReducer', 'CurrentUser', 'UserID']),
		LastName: state.getIn(['InitReducer', 'CurrentUser', 'LastName']),
		FirstName: state.getIn(['InitReducer', 'CurrentUser', 'FirstName']),
		CompName: state.getIn(['InitReducer', 'CurrentComp', 'ShortName']),	

然後 component view 的部分

OK 這樣做完 就可以簡單看到你這個人的人名

But 這滿無聊的 沒什麼特別

比較有趣的是我們用 semantic Ui Modal 來做 可以切換公司的部分

第一 先把資料拉出來

export const GetUserAccessComps = (_compid, _userid, _token) => {
	var formData = new FormData();
	formData.append("token", _token);
	formData.append("UserID", _userid);

	return (dispatch) => {
		fetch("http://xxx.xxx.xxx/api/comp/get_user_access_comps", {
				method: "POST",
				body: formData
			})
			.then(function(response) {
				return response.json();
			})
			.then(function(jsonData) {
				let _currentComp = jsonData.data.filter(function(_ele) {
					return _ele.CompID == _compid
				})[0].company_info;
				// 設定當前要的公司資料
				dispatch({
					type: Update_Current_Comp,
					payload: {
						CurrentComps: _currentComp[0]
					}
				});
				// 寫入目前使用者可以進入的公司
				dispatch({
					type: Insert_User_Access_Comp,
					payload: {
						AllComps: jsonData.data
					}
				});
			})
			.catch(function(e) {
				console.log(e);
			})
	}
};

再來去 redux的model 設定好你要哪些東西 長什麼樣子

export const InitUserData = Immutable.fromJS({
	// 其他測試資料
	'CompData': {
		id: '',
		name: '4',
	},
	'CompList': [{
		id: '123',
		name: '123'
	}],

	// 正式資料
	'CurrentUser': {
		CompID: '',
		UserID: '',
		LastName: '',
		FirstName: ''
	},
	Email: "",
	Password: "",
	IsLogin: false,
	Token: '',
	// 公司裡面現有的成員
	'AllCompMember': [],
	// 控制是否開啟切換多公司畫面
	companyModalOpen: false,
	// 可以進入的公司列表
	'AllComps': [{
		CompID: '',
		ShortName: '',
		TimeZone: '',
		IsActive: '',
		LogoPath: ''
	}],
    ..........
}),

接著 container 要把redux tree store 起來的值 傳進 component

	// 從這裡把State的狀態值抽出來,然後component那邊就可以用this.props.Email 把它放在function 當成參數來傳
	(state) => ({
		Token: state.getIn(['InitReducer', 'Token']),
		CompID: state.getIn(['InitReducer', 'CurrentUser', 'CompID']),
		UserID: state.getIn(['InitReducer', 'CurrentUser', 'UserID']),
		LastName: state.getIn(['InitReducer', 'CurrentUser', 'LastName']),
		FirstName: state.getIn(['InitReducer', 'CurrentUser', 'FirstName']),
		CompName: state.getIn(['InitReducer', 'CurrentComp', 'ShortName']),	
		AllComps: state.getIn(['InitReducer', 'AllComps']),
		companyModalOpen: state.getIn(['InitReducer', 'companyModalOpen']),

並定義兩個方法
一個是打開切換的頁面
一個是選擇公司的動作

(dispatch) => ({
    onEnterInComp: (_compItem, _userid, _token) => () => {
        dispatch(ChangeCurrentComp(_compItem, _userid, _token))
        dispatch(GetUserAccessDiscs(_compItem.get('CompID'), _userid, _token))
    },
    onChangeIsOpenCompModal: (_isopen) => () => (
        dispatch(ChangeIsOpenCompModal(_isopen))
    )
}),

最後 來看 component 這個裡面有些特別的

<div >
  <img src={require('../../images/Logo/458.jpg')}
       style={styles.compLogo}/>
  <span style={{...styles.compName, ...styles.TextLimitation}}>{this.props.CompName}</span>
  <Modal
    trigger={<Button onClick={this.props.onChangeIsOpenCompModal(true)} color="blue" style={{...styles.switchBtn, ...styles.TextLimitation}}>{t('SwitchCompany')}</Button>}
    open={this.props.companyModalOpen}
    onClose={this.props.onChangeIsOpenCompModal(false)}
    basic
    size='fullscreen'>
    <Header icon='browser' content='切換公司' />
    <Modal.Content scrolling>
      <div>
        <Grid>
          {this.props.AllComps.map(function(_item, _key)
          {
              return (  
                <Grid.Column mobile={16} tablet={8} computer={4} key={_key}>
                  <div style={styles.switchComp.wrap}>
                    <div style={styles.switchComp.side}>
                      <Image style={styles.switchComp.logo} 
                             src={require('../../images/companyLogo/Default_Company0.jpg')}
                             onClick={this.props.onEnterInComp(_item, this.props.UserID, this.props.Token)}>
                      </Image>                                  
                    </div>
                    <div style={{...styles.switchComp.side, ...styles.switchComp.rightside}}>
                      <span style={{...styles.switchComp.name, ...styles.TextLimitation}}
                            onClick={this.props.onEnterInComp(_item, this.props.UserID, this.props.Token)}>
                        {_item.get('ShortName')}
                      </span>
                      <label style={styles.switchComp.noreadNum}>0</label>
                      <p style={styles.switchComp.leaveCompText}>{t('ExitCompany')}</p>
                    </div>
                  </div>
                </Grid.Column>
              )
          }, this)}
        </Grid>                 
      </div>
    </Modal.Content>
    <Modal.Actions>
      <Button color='green' onClick={this.props.onChangeIsOpenCompModal(false)} inverted>
        <Icon name='checkmark' /> 關閉
      </Button>
    </Modal.Actions>
  </Modal>
</div>

一般 查得到資料的 我就不解釋了
比較特別是 如果你從 action 做 fetch 然後把一個 array 放進去 store 後
你再拉出來 他會變成一個 list 並不會是 array
所以這時候 你用map的方法 可以繞他
但是你再取值的時候要注意用 {item.get('YOUR PARAM NAME')}
然後

{this.props.AllComps.map(function(_item, _key){}, this)}

這個 ,this 很重要 如果沒有他 你裡面就沒有辦法去做 container 裡面方法的呼叫

後面我們還有 討論組列表 render 的互動 這個請看 Day16


上一篇
【Day 12】Used Request from Redux about MyBox implementation
下一篇
【Day 14】MyBox List Integration
系列文
React.js & Laravel 30天訓練30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言