How to extract index from a button in Listview? - xaml

I have an unusual question. How to extract index from a button in Listview.
I would like <Button Clicked = "indexOne" Text = "{Binding Answers [0]}" /> to have index 0 e.t.c
Sorry for my english.
<ContentPage.Content>
<ScrollView>
<ListView x:Name="elo" Margin="10,0" RowHeight="250">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<Grid >
<StackLayout >
<Label Text="{Binding Question1}" />
<Button Clicked="indexOne" Text="{Binding Answers[0]}" />
<Button Clicked="indexTwo" Text="{Binding Answers[1]}" />
<Button Clicked="indexThree" Text="{Binding Answers[2]}"/>
<Button Clicked="indexFour" Text="{Binding Answers[3]}" />
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
</ContentPage.Content>

Welcome to SO !
You can use the Xamarin.Forms MessagingCenter to achiece that , not sure this is the best way to achieve that . If later have good solutions will update here .
Here is the sample code to explain that .Create a OptionClass to store Option of Question .
public class OptionClass
{
// add QuestionID
public int QuestionID { set; get; }
public string OptionTitle { set; get; }
public int OptionIndex { set; get; }
// add int[] for button command paramater
public int[] IDValues {
get
{
return new int[] { QuestionID, OptionIndex };
}
}
public ICommand OptionChooseCommand { set; get; }
}
Create a QuestionClass class to generate each question data :
public class QuestionClass
{
public string QuestionTitle { set; get; }
// add QuestionID
public int QuestionID { set; get; }
public List<OptionClass> optionClasses { set; get; }
public QuestionClass(string title,List<OptionClass> options, int questionId)
{
optionClasses = new List<OptionClass>();
QuestionTitle = title;
optionClasses = options;
QuestionID = questionId;
}
}
Last , creat a AnsweViewModel to generate list data of questions :
public class AnsweViewModel
{
private MainPage mainPage;
public List<QuestionClass> questionClasses { set; get; }
public AnsweViewModel(MainPage mainPage)
{
this.mainPage = mainPage;
questionClasses = new List<QuestionClass>();
List<OptionClass> optionsOne = new List<OptionClass>();
optionsOne.Add(new OptionClass()
{
QuestionID = 0,
OptionTitle = "A",
OptionIndex = 1,
OptionChooseCommand = new Command<int[]>((int[] value) => {
MessagingCenter.Send<MainPage, int[]>(mainPage, "ButtonInfo", value);
})
});
optionsOne.Add(new OptionClass()
{
QuestionID = 0,
OptionTitle = "B", OptionIndex = 2,
OptionChooseCommand = new Command<int[]>((int[] value) => {
MessagingCenter.Send<MainPage, int[]>(mainPage, "ButtonInfo", value);
})
});
optionsOne.Add(new OptionClass() {
QuestionID = 0,
OptionTitle = "C", OptionIndex = 3,
OptionChooseCommand = new Command<int[]>((int[] value) => {
MessagingCenter.Send<MainPage, int[]>(mainPage, "ButtonInfo", value);
})
});
optionsOne.Add(new OptionClass()
{
QuestionID = 0,
OptionTitle = "D", OptionIndex = 4,
OptionChooseCommand = new Command<int[]>((int[] value) => {
MessagingCenter.Send<MainPage, int[]>(mainPage, "ButtonInfo", value);
})
});
questionClasses.Add(new QuestionClass("Question One", optionsOne, 0) { });
List<OptionClass> optionsTwo = new List<OptionClass>();
optionsTwo.Add(new OptionClass()
{
QuestionID = 1,
OptionTitle = "A",
OptionIndex = 1,
OptionChooseCommand = new Command<int[]>((int[] value) => {
MessagingCenter.Send<MainPage, int[]>(mainPage, "ButtonInfo", value);
})
});
optionsTwo.Add(new OptionClass()
{
QuestionID = 1,
OptionTitle = "B",
OptionIndex = 2,
OptionChooseCommand = new Command<int[]>((int[] value) => {
MessagingCenter.Send<MainPage, int[]>(mainPage, "ButtonInfo", value);
})
});
optionsTwo.Add(new OptionClass()
{
QuestionID = 1,
OptionTitle = "C",
OptionIndex = 3,
OptionChooseCommand = new Command<int[]>((int[] value) => {
MessagingCenter.Send<MainPage, int[]>(mainPage, "ButtonInfo", value);
})
});
questionClasses.Add(new QuestionClass("Question Two", optionsTwo, 1) { });
}
}
Here in Xaml , use Bindable Layouts to show option view . If always options are four items, not need to use this .
<ListView x:Name="elo"
Margin="10,0"
RowHeight="250">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<StackLayout Orientation="Vertical">
<Label Text="{Binding QuestionTitle}" />
<StackLayout BindableLayout.ItemsSource="{Binding optionClasses}" Orientation="Horizontal">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Button Text="{Binding OptionTitle}"
Command="{Binding OptionChooseCommand}"
CommandParameter="{Binding IDValues}"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In ContentPage , code as follow :
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
AnsweViewModel answeViewModel = new AnsweViewModel(this);
elo.ItemsSource = answeViewModel.questionClasses;
MessagingCenter.Subscribe<MainPage,int>(this, "ButtonIndex", (sender,arg) =>
{
Console.WriteLine("Question is " + answeViewModel.questionClasses[arg[0]].QuestionTitle + " Button Index is : " + arg[1]);
DisplayAlert("Question is " + answeViewModel.questionClasses[arg[0]].QuestionTitle, " Button Index is : " + arg[1], "Ok");
// Do something whenever the "Hi" message is received
});
}
}
The updated effect :(not need to care about which cell be selected )

Related

How to change the resolution of AgoraVideoPlayer?

import React from 'react';
import { AgoraVideoPlayer } from "agora-rtc-react";
import { Grid } from "#material-ui/core";
import { useState, useEffect } from "react";
import { useClient } from './settings';
import "./Video.css";
export default function Video(props) {
const { users, tracks } = props;
const client = useClient();
const [gridSpacing, setGridSpacing] = useState(12);
useEffect(() => {
setGridSpacing(Math.max(Math.floor(12 / (users.length + 1)), 4));
}, [users, tracks]);
return (
<Grid container className="VidCon">
<Grid item xs={gridSpacing} className="vidd">
<Grid id='Name'>{client.uid}</Grid>
<AgoraVideoPlayer className="Video"
videoTrack={tracks[1]}
/>
</Grid>
{users.length > 0 &&
users.map((user) => {
if (user.videoTrack) {
return (
<Grid item xs={gridSpacing} className="vidd">
<Grid id='Name'>{user.uid}</Grid>
<AgoraVideoPlayer className="Video"
videoTrack={user.videoTrack}
key={user.uid}
/>
</Grid>
);
} else return null;
})}
</Grid>
);
}
This is the sample code of me using the AgoraVideoPlayer in my react.js app. It works, but i want to change the resolution and aspect ratio of the video that is captured. Please help.

ImageButtonGestureRecognizers for custom button

I have a collection view with my custom buttons.And have a function which change color of images and their background.My problem: it works with every button if I click,I want to make function which will change color and backgroundcolor of my SELECTED button.I thought maybe to make controls:CustomRoundButton.GestureRecognizers but I don`t understand how to write this function.Or maybe other function
<CollectionView ItemsSource="{Binding Cars}"
SelectionMode="None">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"
Span="3" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="90" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Frame CornerRadius="10" BorderColor="Black" Margin="5,5,5,5" Padding="0"
>
<controls:CustomRoundButton TintColor="#616161" HeightRequest="90"
WidthRequest="90" CornerRadius="10" HorizontalOptions="Center"
BackgroundColor="White" ImageSource="heart" Clicked="Button_OnClicked"/>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
private void Button_OnClicked(object sender, EventArgs e)
{
((CustomRoundButton)sender).BackgroundColor = ((Button)sender).BackgroundColor == Color.White
? Color.FromHex("#2979FF")
: Color.White;
CustomRoundButton.SetTintColor((CustomRoundButton)sender, CustomRoundButton.GetTintColor((CustomRoundButton)sender) == Color.FromHex("#616161")
? Color.White
: Color.FromHex("#616161"));
}
enter image description here
I notice you used MVVM, you can achieve it my Command for your controls:CustomRoundButton .
Here is layout code.
<StackLayout>
<!-- Place new controls here -->
<CollectionView x:Name="BillView" ItemsSource="{Binding Cars}"
SelectionMode="None">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"
Span="3" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="90" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Frame CornerRadius="10" BorderColor="Black" Margin="5,5,5,5" Padding="0" >
<controls:CustomRoundButton HeightRequest="90"
WidthRequest="90" CornerRadius="10" HorizontalOptions="Center"
BackgroundColor="{Binding CustButtonColor}" ImageSource="{Binding Image}" Command="{ Binding BindingContext.ChangeCommand, Source={x:Reference Name=BillView} }" CommandParameter="{Binding .}"/>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
Here is layout background code.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
this.BindingContext = new MyModelView();
}
}
Here is code about MyModelView.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Windows.Input;
using Xamarin.Forms;
namespace CollectionViewDemo
{
public class MyModelView
{
public ObservableCollection<Car> Cars { get; set; }
public ICommand ChangeCommand { protected set; get; }
public MyModelView()
{
Cars = new ObservableCollection<Car>();
Cars.Add(new Car() { Image = "unheart.png",CustButtonColor=Color.Default });
Cars.Add(new Car() { Image = "unheart.png", CustButtonColor = Color.Default });
Cars.Add(new Car() { Image = "unheart.png", CustButtonColor = Color.Default });
Cars.Add(new Car() { Image = "unheart.png", CustButtonColor = Color.Default });
Cars.Add(new Car() { Image = "unheart.png", CustButtonColor = Color.Default });
Cars.Add(new Car() { Image = "unheart.png", CustButtonColor = Color.Default });
Cars.Add(new Car() { Image = "unheart.png", CustButtonColor = Color.Default });
Cars.Add(new Car() { Image = "unheart.png", CustButtonColor = Color.Default });
Cars.Add(new Car() { Image = "unheart.png", CustButtonColor = Color.Default });
ChangeCommand = new Command<Car>((key) =>
{
var car = key as Car;
if (car.Image == "heart.png")
{
car.Image = "unheart.png"; car.CustButtonColor = Color.Default;
}
else
{
car.Image = "heart.png";
car.CustButtonColor = Color.Red;
}
});
}
}
public class Car: INotifyPropertyChanged
{
string image;
public string Image
{
set
{
if (image != value)
{
image = value;
OnPropertyChanged("Image");
}
}
get
{
return image;
}
}
Color _custButtonColor;
public Color CustButtonColor
{
set
{
if (_custButtonColor != value)
{
_custButtonColor = value;
OnPropertyChanged("CustButtonColor");
}
}
get
{
return _custButtonColor;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Here is running GIF.
======Update=======
but can you help me that only ONE selected button change background color and color of the icon on the image?
Do you want to achieve the result following GIF?
If so, please change the code of ChangeCommand.
ChangeCommand = new Command<Car>((key) =>
{
foreach (var item in Cars)
{
item.Image = "unheart.png";
item.CustButtonColor = Color.Default;
}
var car = key as Car;
car.Image = "heart.png";
car.CustButtonColor = Color.Red;
});
=======Update2=========
If you have different pictures, you can add a property called Name. we can reset ObservableCollection by name, when we click the Button.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Windows.Input;
using Xamarin.Forms;
namespace CollectionViewDemo
{
public class MyModelView
{
public ObservableCollection<Car> Cars { get; set; }
public ICommand ChangeCommand { protected set; get; }
public MyModelView()
{
Cars = new ObservableCollection<Car>();
Cars.Add(new Car() {Name="Audio", Image = "unheart.png",CustButtonColor=Color.Default });
Cars.Add(new Car() {Name="BMW", Image = "faded_div.jpg", CustButtonColor = Color.Default });
Cars.Add(new Car() {Name="BENZ", Image = "myIcon.png", CustButtonColor = Color.Default });
Cars.Add(new Car() {Name="LEUX", Image = "wind.jpg", CustButtonColor = Color.Default });
var DefaultCars= new ObservableCollection<Car>();
DefaultCars = Cars;
ChangeCommand = new Command<Car>((key) =>
{
//Rest the `ObservableCollection` by name.
foreach (var item in Cars)
{
if (item.Name.Equals("Audio"))
{
item.Image = "unheart.png";
item.CustButtonColor = Color.Default;
}else if (item.Name.Equals("BMW"))
{
item.Image = "faded_div.jpg";
item.CustButtonColor = Color.Default;
}
else if (item.Name.Equals("BENZ"))
{
item.Image = "myIcon.png";
item.CustButtonColor = Color.Default;
}
else if (item.Name.Equals("LEUX"))
{
item.Image = "wind.jpg";
item.CustButtonColor = Color.Default;
}
}
var car = key as Car;
car.Image = "heart.png";
car.CustButtonColor = Color.Red;
});
}
}
public class Car: INotifyPropertyChanged
{
public string Name { get; set; }
string image;
public string Image
{
set
{
if (image != value)
{
image = value;
OnPropertyChanged("Image");
}
}
get
{
return image;
}
}
Color _custButtonColor;
public Color CustButtonColor
{
set
{
if (_custButtonColor != value)
{
_custButtonColor = value;
OnPropertyChanged("CustButtonColor");
}
}
get
{
return _custButtonColor;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Here is running GIF.
=========Update 3==============
You can set different icon for different button when you click it(set the different image by Name).
ChangeCommand = new Command<Car>((key) =>
{
//reset the item to default image and background.
foreach (var item in Cars)
{
if (item.Name.Equals("Audio"))
{
item.Image = "unheart.png";
item.CustButtonColor = Color.Default;
}else if (item.Name.Equals("BMW"))
{
item.Image = "faded_div.jpg";
item.CustButtonColor = Color.Default;
}
else if (item.Name.Equals("BENZ"))
{
item.Image = "myIcon.png";
item.CustButtonColor = Color.Default;
}
else if (item.Name.Equals("LEUX"))
{
item.Image = "wind.jpg";
item.CustButtonColor = Color.Default;
}
}
//set the different image by Name
var car = key as Car;
if (car.Name.Equals("BENZ"))
{
car.Image = "sandwich.png";
}else if (car.Name.Equals("BMW"))
{
car.Image = "rose.png";
}
else
{
car.Image = "heart.png";
}
car.CustButtonColor = Color.Red;
});
}
}
Here is running GIF.
Here is demo.
https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/CollectionViewDemo.zip

Create sorting in a blueprintjs table

I want to make my columns sortable in terms of ascending and descending. The blueprintjs talks about how this is possible, but isn't exactly clear on the steps on how to implement it. I have a table I created in this format. I want to be able to sort the numbers ascending and descending. I attempted creating a menu and all, but nothing seemed to solve my probelm.
class DataTable extends Component {
renderCell = (rowIndex, colIndex) => {
return (
<Cell>
{rowIndex}
</Cell>
);
};
render() {
const { data } = this.props;
const { length } = data;
return (
<Table numRows={length} numFrozenColumns={1}>
<Column name="Campaign" cellRenderer={this.renderCell} />
<Column name="Date Sent" cellRenderer={this.renderCell} />
</Table>
);
}
}
Here you have one simple example. I hope it will help.
import { Column, ColumnHeaderCell, Table, Cell } from "#blueprintjs/table";
import { Menu, MenuItem } from "#blueprintjs/core";
export const SortableTable = () => {
const [items] = useState([
{ _id: 1, campaign: "L", email: "some1#test.com" },
{ _id: 2, campaign: "A", email: "some2#test.com" },
{ _id: 3, campaign: "V", email: "some3#test.com" }
]);
const cellRenderer = (rowIndex, type) => {
return <Cell>{items[rowIndex][type]}</Cell>;
};
const handleSortCampaignAsc = () => {
// todo sort asc
};
const handleSortCampaignDesc = () => {
// todo sort desc
};
const menuRenderer = (sortAsc, sortDesc) => (
<Menu>
<MenuItem icon="sort-asc" onClick={sortAsc} text="Sort Asc" />
<MenuItem icon="sort-desc" onClick={sortDesc} text="Sort Desc" />
</Menu>
);
const header = () => (
<ColumnHeaderCell
name="Campaign"
menuRenderer={menuRenderer(handleSortCampaignAsc, handleSortCampaignDesc)}
/>
);
return (
<Table numRows={items.length}>
<Column
columnHeaderCellRenderer={header}
cellRenderer={(rowIndex) => cellRenderer(rowIndex, "campaign")}
/>
<Column
name="Email"
cellRenderer={(rowIndex) => cellRenderer(rowIndex, "email")}
/>
</Table>
);
};
P.S. Don't forget to add dependencies for the icons.

How can I make an entire row clickable in a DetailsList component? (office-ui-fabric)

I've been using the DetailsList component but haven't found a way to make an entire row clickable - is there a sample code snippet or pointers on how this can be achieved?
https://developer.microsoft.com/en-us/fabric#/components/detailslist
Overriding onRenderRow worked for me.
const _columns: IColumn[] = [
{
key: 'name',
name: 'Name',
fieldName: 'name',
minWidth: 100,
maxWidth: 200,
isResizable: true
},
{
key: 'value',
name: 'Value',
fieldName: 'value',
minWidth: 100,
maxWidth: 200,
isResizable: true,
}
];
const _items = Array.apply(null, Array(10)).map((_: any, num: number) => ({
key: num.toString(),
name: `Item ${num.toString()}`,
value: num.toString()
}));
class Content extends React.Component {
private _renderRow(props: Fabric.IDetailsRowProps, defaultRender: any): JSX.Element {
return (
<Fabric.DetailsRow {...props} onClick={() => alert('click')}/>
);
}
public render() {
return (
<Fabric.Fabric>
<Fabric.DetailsList
items={ _items }
columns={ _columns.concat(..._columns, ..._columns, ..._columns) }
onRenderRow={this._renderRow}
/>
</Fabric.Fabric>
);
}
}
ReactDOM.render(
<Content />,
document.getElementById('content')
);
Here is th e single click solution,
Use onActiveItemChanged prop like:
const _onActiveItemChanged = (item): void => {
alert(`Item invoked: ${JSON.stringify(item)}`);
};
here is the DetailList
<DetailsList
items={assessmentList}
compact={false}
columns={columns}
onActiveItemChanged={_onActiveItemChanged }
/>
Please onItemInvoked Property and method. But it works on double click. I am also looking for single click solution
const onItemInvoked = (item): void => {
alert(`Item invoked: ${JSON.stringify(item)}`);
};
<DetailsList
items={assessmentList}
compact={false}
columns={columns}
selectionMode={SelectionMode.multiple}
getKey={_getKey}
setKey="multiple"
layoutMode={DetailsListLayoutMode.justified}
checkboxVisibility={CheckboxVisibility.hidden}
isHeaderVisible={true}
selectionPreservedOnEmptyClick={false}
enterModalSelectionOnTouch={true}
ariaLabelForSelectionColumn="Toggle selection"
ariaLabelForSelectAllCheckbox="Toggle selection for all items"
checkButtonAriaLabel="Select Checkbox"
onRenderRow={onRenderRow}
onItemInvoked={onItemInvoked}
onRenderDetailsHeader={(headerProps, defaultRender) => {
return (
<Sticky
stickyPosition={StickyPositionType.Header}
isScrollSynced={true}
stickyBackgroundColor="transparent"
>
<div className="text-center">{defaultRender(headerProps)}</div>
</Sticky>
);
}}
/>
Use onRenderRow and cloneElement to attach an onClick listener:
import React, { useCallback, cloneElement } from 'react';
import { DetailsList } from '#fluentui/react';
const Component = () => {
const onItemInvoked = useCallback( ( item ) => {
console.log( item );
}, [] );
const onRenderRow = useCallback( ( row, defaultRender ) => {
return cloneElement( defaultRender( row ), { onClick: () => onItemInvoked( row.item ) } )
}, [ onItemInvoked ] );
return (
<DetailsList
onRenderRow={ onRenderRow }
/>
);
};

react dnd nesting level on hover

I want to implement a drop system where if drop targets are nested you can cycle between them using the mouse scroll wheel (or have an automatic cycle happen after a certain amount of time) this will be particularly useful because many of the nested targets occupy the exact same areas on screen.
I'm presently thinking that I could use a callback passed down from the container that could be used by drop targets to register/de-register themselves when their hover function is called/when isOver prop changes but it's very coupled and I have to pass props into the DropTargets from the container, in the real world application there will be an unknown number of levels between container and drop target so I'd likely have to set up some kind of callback system, overall its not an ideal solution. Also I'm not sure how to ensure the correct order when cycling as the drop targets don't know how deeply nested they are (see code below for how I've implemented this). Is there a cleaner way to implement such a system?
#DragDropContext(HTML5Backend)
export default class Container extends Component {
constructor (props) {
super(props);
this.state = {
bins: []
};
this.status = {};
this._cycle = this.cycle.bind(this);
this._register = this.register.bind(this);
this._deregister = this.deregister.bind(this);
}
componentWillUnmount () {
if (this.timer) {
window.clearInterval(this.timer);
}
}
register (name) {
if (this.state.bins.findIndex(e => e === name) === -1) {
this.setState({
bins: this.state.bins.concat(name)
});
if (!this.timer) {
this.cycledBins = [];
this.timer = window.setInterval(this._cycle, 3000);
this._cycle();
}
}
}
deregister (name) {
if (this.state.bins.findIndex(e => e === name) !== -1) {
const bins = this.state.bins.filter((e) => e === name);
this.setState({
bins
});
if (!bins.length) {
window.clearInterval(this.timer);
this.timer = undefined;
}
}
}
cycle () {
this.status = {};
const bins = this.state.bins;
let activeBin = -1;
for (let i = 0; i < bins.length; i += 1) {
if (this.cycledBins.findIndex(bin => bin === bins[i]) === -1) {
activeBin = bins[i];
break;
}
}
if (activeBin === -1) {
activeBin = bins[0];
this.cycledBins = [];
}
this.cycledBins.push(activeBin);
this.activeBin = activeBin;
this.status[activeBin] = {
isActive: true,
isOnlyActive: bins.length === 1
}
this.forceUpdate();
}
render () {
return (
<div>
bins = {JSON.stringify(this.state.bins)}<br />
cycledBins = {JSON.stringify(this.cycledBins)}
<div style={{ overflow: 'hidden', clear: 'both' }}>
<Dustbin name="Outer" register={this._register} deregister={this._deregister} status={this.status["Outer"]} >
<Dustbin name="Middle" register={this._register} deregister={this._deregister} status={this.status["Middle"]} >
<Dustbin name="Inner" register={this._register} deregister={this._deregister} status={this.status["Inner"]} />
</Dustbin>
</Dustbin>
</div>
<div style={{ overflow: 'hidden', clear: 'both' }}>
<Box name='Glass' />
<Box name='Banana' />
<Box name='Paper' />
</div>
</div>
);
}
}
const boxTarget = {
hover(props) {
props.register(props.name);
}
};
#DNDDropTarget('Box', boxTarget, (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver()//,
//canDrop: monitor.canDrop()
}))
export default class Dustbin extends Component {
static propTypes = {
connectDropTarget: PropTypes.func.isRequired,
isOver: PropTypes.bool.isRequired//,
//canDrop: PropTypes.bool.isRequired
};
componentWIllMount () {
if (!this.props.isOver) {
this.props.deregister(this.props.name);
}
}
componentWillReceiveProps (nextProps) {
if (nextProps.isOver !== this.props.isOver && !nextProps.isOver) {
this.props.deregister(this.props.name);
}
}
render() {
const { canDrop, isOver, connectDropTarget, status } = this.props;
const isOnlyActive = status && status.isOnlyActive;
let isActive = status && status.isActive;
if (!isOver && isActive) {
isActive = false;
}
return connectDropTarget(
<div>
<DropTarget position={BEFORE} shown={isActive} />
{ isActive && !isOnlyActive ? '(' + this.props.name + ')' : undefined }
{ this.props.children ? this.props.children : (
<div style={style}>
{ isActive ?
'Release to drop' :
'Drag a box here'
}
</div>
) }
<DropTarget position={AFTER} shown={isActive} />
</div>
);
}
}