Skip to main content
removed typo
Source Link

Oo thisThis all works, but having to use the dynamic type to circumvent strong typing generates a code smell from a (potentially bad) design policy caused by not wanting components to make out of process calls (database updates), and only having pages define methods that make that make out of process calls. Is my design policy fine and this is just one of the things I need to do, or should I abandon the policy (on this early project)?

Oo this all works, but having to use the dynamic type to circumvent strong typing generates a code smell from a (potentially bad) design policy caused by not wanting components to make out of process calls (database updates), and only having pages define methods that make that make out of process calls. Is my design policy fine and this is just one of the things I need to do, or should I abandon the policy (on this early project)?

This all works, but having to use the dynamic type to circumvent strong typing generates a code smell from a (potentially bad) design policy caused by not wanting components to make out of process calls (database updates), and only having pages define methods that make that make out of process calls. Is my design policy fine and this is just one of the things I need to do, or should I abandon the policy (on this early project)?

formatting for readability
Source Link
@inject ContextMenuService ContextMenuService
<RadzenStack Gap="0px" Orientation="Orientation.Horizontal">

    <RadzenButton Text=@SaveText Click="SaveAction" class="rz-border-radius-0"
  ButtonStyle="ButtonStyle"
  />
    <RadzenButton Icon="expand_more"
  class="rz-border-radius-0"
  ButtonStyle="ButtonStyle"
  Click="@(args=>ShowDropdownMenu(args))"
  Visible=hasContextItems
  />
</RadzenStack>

@code{
[Parameter]
public Func<Task> SaveAction { get; set; }
[Parameter]
public List<ContextMenuItem> ContextMenuList { get; set; } = new List<ContextMenuItem>();
[Parameter]
public ButtonStyle ButtonStyle { get; set; }
[Parameter]
public string SaveText { get; set; }
private bool hasContextItems => ContextMenuList.Count > 0; 

void ShowDropdownMenu(MouseEventArgs args)
{
  ContextMenuService.Open(args,
  ContextMenuList, OnMenuItemClick
 );
} 

async void OnMenuItemClick(MenuItemEventArgs args)
{
    dynamic method = args.Value;
    await method.Invoke();
    ContextMenuService.Close();
}
}
@page "/myPage"
<RadzenTabs RenderMode="TabRenderMode.Client" TabPosition="TabPosition.Left" u/bind-SelectedIndex=@selectedPricingModelIndex>
    <Tabs>
        
        u/foreach@foreach(var model in pricingModels)
        {
            int i = pricingModels.IndexOf(model);
            <RadzenTabsItem [email protected]>
                <PricingModelComponent Model=@pricingModels[i]
                    SaveAllPricingModelChanges="SavePricingModelAsync"
                    SaveBoardChanges="SaveBoardChangesAsync"
                />
            </RadzenTabsItem>
        }
    </Tabs>
</RadzenTabs>
@code{
private async Task SavePricingModelAsync(PricingModel model)
{
    await DataSource.UpdatePricingModelAsync(model);
}

private async Task SaveBoardChangesAsync(PricingModel model, List<Board> boards)
{
    model.Boards = boards;
    await DataSource.UpdatePricingModelAsync(model);
}
}
@inject ContextMenuService ContextMenuService
<RadzenStack Gap="0px" Orientation="Orientation.Horizontal">

<RadzenButton Text=@SaveText Click="SaveAction" class="rz-border-radius-0"
 ButtonStyle="ButtonStyle"
 />
<RadzenButton Icon="expand_more"
 class="rz-border-radius-0"
 ButtonStyle="ButtonStyle"
 Click="@(args=>ShowDropdownMenu(args))"
 Visible=hasContextItems
 />
</RadzenStack>

@code{
[Parameter]
public Func<Task> SaveAction { get; set; }
[Parameter]
public List<ContextMenuItem> ContextMenuList { get; set; } = new List<ContextMenuItem>();
[Parameter]
public ButtonStyle ButtonStyle { get; set; }
[Parameter]
public string SaveText { get; set; }
private bool hasContextItems => ContextMenuList.Count > 0;
void ShowDropdownMenu(MouseEventArgs args)
{
ContextMenuService.Open(args,
 ContextMenuList, OnMenuItemClick
 );
}
async void OnMenuItemClick(MenuItemEventArgs args)
{
dynamic method = args.Value;
await method.Invoke();
ContextMenuService.Close();
}
}
@page "/myPage"
<RadzenTabs RenderMode="TabRenderMode.Client" TabPosition="TabPosition.Left" u/bind-SelectedIndex=@selectedPricingModelIndex>
    <Tabs>
        
        u/foreach(var model in pricingModels)
        {
            int i = pricingModels.IndexOf(model);
            <RadzenTabsItem [email protected]>
                <PricingModelComponent Model=@pricingModels[i]
                    SaveAllPricingModelChanges="SavePricingModelAsync"
                    SaveBoardChanges="SaveBoardChangesAsync"
                />
            </RadzenTabsItem>
        }
    </Tabs>
</RadzenTabs>
@code{
private async Task SavePricingModelAsync(PricingModel model)
{
    await DataSource.UpdatePricingModelAsync(model);
}

private async Task SaveBoardChangesAsync(PricingModel model, List<Board> boards)
{
    model.Boards = boards;
    await DataSource.UpdatePricingModelAsync(model);
}
}
@inject ContextMenuService ContextMenuService
<RadzenStack Gap="0px" Orientation="Orientation.Horizontal">

    <RadzenButton Text=@SaveText Click="SaveAction" class="rz-border-radius-0" ButtonStyle="ButtonStyle" />
    <RadzenButton Icon="expand_more" class="rz-border-radius-0" ButtonStyle="ButtonStyle" Click="@(args=>ShowDropdownMenu(args))" Visible=hasContextItems />
</RadzenStack>

@code{
[Parameter]
public Func<Task> SaveAction { get; set; }
[Parameter]
public List<ContextMenuItem> ContextMenuList { get; set; } = new List<ContextMenuItem>();
[Parameter]
public ButtonStyle ButtonStyle { get; set; }
[Parameter]
public string SaveText { get; set; }
private bool hasContextItems => ContextMenuList.Count > 0; 

void ShowDropdownMenu(MouseEventArgs args)
{
  ContextMenuService.Open(args, ContextMenuList, OnMenuItemClick);
} 

async void OnMenuItemClick(MenuItemEventArgs args)
{
    dynamic method = args.Value;
    await method.Invoke();
    ContextMenuService.Close();
}
}
@page "/myPage"
<RadzenTabs RenderMode="TabRenderMode.Client" TabPosition="TabPosition.Left" u/bind-SelectedIndex=@selectedPricingModelIndex>
    <Tabs>
        
        @foreach(var model in pricingModels)
        {
            int i = pricingModels.IndexOf(model);
            <RadzenTabsItem [email protected]>
                <PricingModelComponent Model=@pricingModels[i]
                    SaveAllPricingModelChanges="SavePricingModelAsync"
                    SaveBoardChanges="SaveBoardChangesAsync"
                />
            </RadzenTabsItem>
        }
    </Tabs>
</RadzenTabs>
@code{
private async Task SavePricingModelAsync(PricingModel model)
{
    await DataSource.UpdatePricingModelAsync(model);
}

private async Task SaveBoardChangesAsync(PricingModel model, List<Board> boards)
{
    model.Boards = boards;
    await DataSource.UpdatePricingModelAsync(model);
}
}
edited body
Source Link
toolic
  • 3.9k
  • 2
  • 16
  • 52

I'm working on a side project. One of the design decisions is that components shouldn't do any database calling (if this is wrong or impractical then i'mI'm open to disregarding this design policy). I'm also using radzen component library, but has no bearing on this. So i

I have a button component that is basically two buttons. one for save (a sub part of an object), and a dropdown/context button to save all (all aspects of a more complex object). this button component is a component and can be used in multiple places. so my idea is to pass the save methods to the button from a parent page. but what's happening in practice is that the save component is a child in another component. this is no big deal, the page defines the save methods, passes it to the component which then passes to the child. where things get hairy is that the method definition is not really definable on the button. sometimes i'mI'm passing a func<Task> other times i'm passing func<myType,Task>. so to account for this is i'mI'm setting the method as a dynamic and calling invoke on that. Here's how that looks.

soOo this all works, but having to use the dynamic type to circumvent strong typing generates a code smell from a (potentially bad) design policy caused by not wanting components to make out of process calls (database updates), and only having pages define methods that make that make out of process calls. Is Is my design policy fine and this is just one of the things iI need to do, or should iI abandon the policy (on this early project).?

I'm working on a side project. One of the design decisions is that components shouldn't do any database calling (if this is wrong or impractical then i'm open to disregarding this design policy). I'm also using radzen component library, but has no bearing on this. So i have a button component that is basically two buttons. one for save (a sub part of an object), and a dropdown/context button to save all (all aspects of a more complex object). this button component is a component and can be used in multiple places. so my idea is to pass the save methods to the button from a parent page. but what's happening in practice is that the save component is a child in another component. this is no big deal, the page defines the save methods, passes it to the component which then passes to the child. where things get hairy is that the method definition is not really definable on the button. sometimes i'm passing a func<Task> other times i'm passing func<myType,Task>. so to account for this is i'm setting the method as a dynamic and calling invoke on that. Here's how that looks.

so this all works, but having to use the dynamic type to circumvent strong typing generates a code smell from a (potentially bad) design policy caused by not wanting components to make out of process calls (database updates), and only having pages define methods that make that make out of process calls. Is my design policy fine and this is just one of the things i need to do, or should i abandon the policy (on this early project).

I'm working on a side project. One of the design decisions is that components shouldn't do any database calling (if this is wrong or impractical then I'm open to disregarding this design policy). I'm also using radzen component library, but has no bearing on this.

I have a button component that is basically two buttons. one for save (a sub part of an object), and a dropdown/context button to save all (all aspects of a more complex object). this button component is a component and can be used in multiple places. so my idea is to pass the save methods to the button from a parent page. but what's happening in practice is that the save component is a child in another component. this is no big deal, the page defines the save methods, passes it to the component which then passes to the child. where things get hairy is that the method definition is not really definable on the button. sometimes I'm passing a func<Task> other times i'm passing func<myType,Task>. so to account for this is I'm setting the method as a dynamic and calling invoke on that. Here's how that looks.

Oo this all works, but having to use the dynamic type to circumvent strong typing generates a code smell from a (potentially bad) design policy caused by not wanting components to make out of process calls (database updates), and only having pages define methods that make that make out of process calls. Is my design policy fine and this is just one of the things I need to do, or should I abandon the policy (on this early project)?

Source Link
Loading