PDA

View Full Version : Component column with multiple coponents



lbrohan
Dec 09, 2020, 9:47 AM
I would like to have two component columns, whole with nuch of controls, that would be displayed according some logic
"some logic means" that if value is equal to predefined value, only some of controls will display in the particular column and as well only some controls will display in next columns ( so list of controls displayed in second column is dependent on value of the control in the first column)

in example (little modified https://examples5.ext.net/#/GridPanel/ComponentColumn/Editor/ )



<%@ Page Language="C#" %>

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
this.Store1.DataSource = new object[]
{
new object[] { },

};

this.Store1.DataBind();
}
}
</script>

<!DOCTYPE html>

<html>
<head runat="server">
<title>ComponentColumn Editor - Ext.NET Examples</title>

</head>
<body>
<script>
Ext.onReady(function() {
var grid = Ext.getCmp('grid');

for (var i = 0; i < grid.columns.length; i++) {
var column = grid.columns[i];

if (column.dataIndex == 'NumberInLeftColumn') {
column.on('bind', numberInLeft_bind, grid);
}

}
});

function numberInLeft_bind(column, cmp, record) {

var leftNumber = cmp.down('#leftNumber');
leftNumber.on('change', Ext.bind(leftNumber_change, this, [column, cmp, record, leftNumber], false));

}

function leftNumber_change(column, cmp, record, leftNumber) {
var text1 = cmp.down('#text1');
var number1 = cmp.down('#number1');
var value = leftNumber.getValue();

text1.setVisible(value == 1);
number1.setVisible(value != 1);

// here I would like to set record.data.NumberInLeftColumn to the "value" variable, record.set('NumberInLeftColumn', value);
// and I would like to display edit fields in next column using same logic
}
</script>
<form runat="server">
<ext:ResourceManager runat="server" />

<h1>ComponentColumn as Editor</h1>

<ext:GridPanel
runat="server"
Title="ComponentColumn Editor"
Width="1000"
ID="grid"
IDMode="Static"
Height="325">
<Store>
<ext:Store ID="Store1" runat="server">
<Model>
<ext:Model runat="server">
<Fields>
<ext:ModelField Name="NumberInLeftColumn" Type="Int" />
<ext:ModelField Name="Text1InLeft" Type="String" />
<ext:ModelField Name="Text2InLeft" Type="String" />
<ext:ModelField Name="Text1" Type="Int" />
<ext:ModelField Name="Number1" Type="Int" />

</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<ColumnModel runat="server">
<Columns>
<ext:ComponentColumn
runat="server"
Editor="true"
DataIndex="NumberInLeftColumn"
Flex="1"
Text="Integer">
<Component>
<ext:Container runat="server">
<LayoutConfig>
<ext:HBoxLayoutConfig />
</LayoutConfig>
<Items>
<ext:NumberField runat="server" ItemID="leftNumber" Flex="1"/>

<ext:TextField runat="server" FieldLabel="text 1" Hidden="true" ItemID="text1" Flex="1"/>
<ext:NumberField runat="server" FieldLabel="number 1" Hidden="true" ItemID="number1" Flex="1"/>
</Items>

</ext:Container>
</Component>
</ext:ComponentColumn>


<ext:ComponentColumn
runat="server"
Editor="true"
DataIndex="Text1"
Flex="1"
Text="Text">
<Component>
<ext:Container runat="server">
<Items>
<ext:TextField runat="server" FieldLabel="text 1" Hidden="true" ItemID="text1"/>
<ext:NumberField runat="server" FieldLabel="number 1" Hidden="true" ItemID="number1"/>
</Items>
</ext:Container>

</Component>
</ext:ComponentColumn>

</Columns>
</ColumnModel>
</ext:GridPanel>
</form>
</body>
</html>


as you can see, if value of the first textbox is 1 , it will display textfield, if other then number field

what is missing:
1) setting value of the first textbox to store ( if I uncomment record.set('NumberInLeftColumn', value); it will end with js exception)
2) according value if first column, I would like to display/hide controls in second column


Note
as an alternative - I was thinking whether it is not possible to construct componetn column "dynamically in javascript" - in when the grid is going to render, handle some its event, and assign to each cell only controls that i want to display (so rather then having on each cell bunch of controls, each hidden, assign only the controls I want to show)

Thanks

fabricio.murta
Dec 09, 2020, 2:36 PM
Hello @Ibrohan!

Can you provide some mock data to illustrate better the scenario you are envisioning? It might be relevant if we want to understand criteria you wanted to apply to show or not components in a given column for a given row...


Note
as an alternative - I was thinking whether it is not possible to construct componetn column "dynamically in javascript"

When I read this a keyword came to mind: PrepareCommand. This may be changing a little the context from Component Column to Command Column but I believe in your case it may fit your needs. In the other hand, the examples I'm going to show basically work by hiding existing components to each row, not actually dynamically making them.

Here's a list of examples that may inspire you to have such behavior to work:

- GridPanel > Commands > Cell_Command (https://examples5.ext.net/#/GridPanel/Commands/Cell_Command/)
- GridPanel > Commands > Group_Command (https://examples5.ext.net/#/GridPanel/Commands/Group_Command/)
- GridPanel > Commands > Image_Command (https://examples5.ext.net/#/GridPanel/Commands/Image_Command/)
- GridPanel > Commands > Prepare_Commands (https://examples5.ext.net/#/GridPanel/Commands/Prepare_Commands/)
- GridPanel > Commands > Prepare_Toolbar (https://examples5.ext.net/#/GridPanel/Commands/Prepare_Toolbar/)
- GridPanel > Data_Presentation > Data_Prepare (https://examples5.ext.net/#/GridPanel/Data_Presentation/Data_Prepare/)

In particular, the last one, is not about PrepareCommand, but using a converter to a data field to dynamically handle what's going to be rendered in the cell -- and this may be the entry point for the fully dynamic solution -- rendering the components to the cell manually. It could become hard to tackle if you have big grids (with many rows) and don't want to disable buffered rendering (https://examples5.ext.net/#/GridPanel/Infinite_Scrolling/Buffered_Scrolling/), actually using a renderer for the column (https://examples5.ext.net/#/GridPanel/ArrayGrid/ArrayWithPaging/) should be the way to go in that path.

So, if the examples above don't help, you may add a little more information (with the mock data), to give us an idea on what you wanted to show/hide in the grid depending on which value on the data, then we could think on something based on your test case.

Hope this helps, nevertheless!

lbrohan
Dec 09, 2020, 3:48 PM
OK thanks

I would like to avoid using rendered,as that would means doing everything in html (means stretching of the components, preparing html)

I'm not sure i understand what data mock you are aksing for

in our application we start with completelly empty (single ) row, so practically we start really with


this.Store1.DataSource = new object[]
{
new object[] { },

};


equivalent

thenaccording values in first control in grid, rest of components in next columns are rendered

So is it possible somehow to show/hide components in one column based on values in another columns
(components stands for dropdownlists textareas, number fields and checkboxes)

fabricio.murta
Dec 09, 2020, 6:31 PM
Hello @Ibrohan!


I'm not sure i understand what data mock you are aksing for

in our application we start with completelly empty (single ) row, so practically we start really with

Ok, I see what you mean and it now makes sense.


1) setting value of the first textbox to store ( if I uncomment record.set('NumberInLeftColumn', value); it will end with js exception)

Right. It seems setting the value when you are "supposedly" setting the value of the column is triggering a loop. Seems to be enough to "silently" set the column value, thus record.set('NumberInLeftColumn', value, { silent: true }); should do the trick here.


2) according value if first column, I would like to display/hide controls in second column

I get here it would be enough for demonstration purposes just do the same logic in your lines 53, 54 to the next column (or a column which data index is Text1, etc), thus displaying either fields, right?

For that you can just get the related column from the current one's context, and then adjust the inner components' display status.

You would then probably want the hidden/shown components to change store values as they are changed. For that just add listeners and similarly to the leftNumber_change() function, get the related grid record and silently change the grid record field. I haven't in-depth tested what this silent option could negatively impact on your grid, but the values are reflected to the store correctly. So you should be good with that for a start.

I have tried to simplify a bit your test case and apply the suggestions I did above, resulting in this working code. I just didn't add the individual components' listeners to change the other record fields as it would just be a bit repetitious, but let us know if you run into problems implementing that.



<%@ Page Language="C#" %>

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
this.Store1.DataSource = new object[]
{
new object[] { }
};

this.Store1.DataBind();
}
}
</script>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Show/hide components according to value - Ext.NET Examples</title>
</head>
<body>
<script>
function leftNumber_change(field) {
var cell_container = field.up(),
record = cell_container.record,
text1 = cell_container.down('#text1'),
number1 = cell_container.down('#number1'),
value = field.getValue(),
context = cell_container.column,
column = context.column,
all_columns = context.grid.getColumns(),
related_column = all_columns.find(function (col) { return col.dataIndex == "Text1" }),
related_component = related_column.getComponent(context.rowIndex),
related_text1 = related_component.down('#text1'),
related_number1 = related_component.down('#number1');

text1.setVisible(value == 1);
number1.setVisible(value != 1);

related_text1.setVisible(value == 1);
related_number1.setVisible(value != 1);

record.set(column.dataIndex, value, { silent: true });
}
</script>
<form runat="server">
<ext:ResourceManager runat="server" />

<h1>ComponentColumn as Editor</h1>

<ext:GridPanel
runat="server"
Title="ComponentColumn Editor"
Width="1000"
ID="grid"
IDMode="Static"
Height="325">
<Store>
<ext:Store ID="Store1" runat="server">
<Model>
<ext:Model runat="server">
<Fields>
<ext:ModelField Name="NumberInLeftColumn" Type="Int" />
<ext:ModelField Name="Text1InLeft" Type="String" />
<ext:ModelField Name="Text2InLeft" Type="String" />
<ext:ModelField Name="Text1" Type="Int" />
<ext:ModelField Name="Number1" Type="Int" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<ColumnModel runat="server">
<Columns>
<ext:ComponentColumn
runat="server"
Editor="true"
DataIndex="NumberInLeftColumn"
Flex="1"
Text="Integer">
<Component>
<ext:Container runat="server">
<LayoutConfig>
<ext:HBoxLayoutConfig />
</LayoutConfig>
<Items>
<ext:NumberField runat="server" ItemID="leftNumber" Flex="1">
<Listeners>
<Change Fn="leftNumber_change" />
</Listeners>
</ext:NumberField>
<ext:TextField runat="server" FieldLabel="text 1" Hidden="true" ItemID="text1" Flex="1"/>
<ext:NumberField runat="server" FieldLabel="number 1" Hidden="true" ItemID="number1" Flex="1"/>
</Items>
</ext:Container>
</Component>
</ext:ComponentColumn>
<ext:ComponentColumn
runat="server"
Editor="true"
DataIndex="Text1"
Flex="1"
Text="Text">
<Component>
<ext:Container runat="server">
<Items>
<ext:TextField runat="server" FieldLabel="text 1" Hidden="true" ItemID="text1"/>
<ext:NumberField runat="server" FieldLabel="number 1" Hidden="true" ItemID="number1"/>
</Items>
</ext:Container>
</Component>
</ext:ComponentColumn>
</Columns>
</ColumnModel>
</ext:GridPanel>
</form>
</body>
</html>


As far as I tested here, it worked without issues.