Add components based on string variables in Blazor - razor

We're creating a dynamic page of components in Blazor. The intention is to have dynamic applets displayed on a page. The idea is that we have a list of strings which correspond to Component names. We read through the string list and for each one, instantiate a blazor component or render fragment. These are just simple components, no passed in parameters or the like. ie:
string[] componentsStrings = {"Component1", "Component2"};
Expected output:
<Component1 />
<Component2 />
We can't come up with a way to do this. It seems like a fairly standard thing to do, but perhaps not? Does anyone know if this is even possible?

You will have to programmatically create a component which adds your custom components on the page using RenderTreeBuilder.
Chris Sainty has a blog post on this which you can read here: https://chrissainty.com/building-components-via-rendertreebuilder/
Basically there is an override for BuildRenderTree in the ComponentBase class which can be used:
public class Menu : ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenElement(0, "nav");
builder.AddAttribute(1, "class", "menu");
}
}
Here is another tutorial.
Some tips from here:
Place base.BuildRenderTree(builder); at the start of the
BuildRenderTree method , not at the end.
Always start with the value 0 for the sequence parameter.

Related

Hybris backoffice extend widget

This is the syncronization popup (com.hybris.backoffice.widgets.syncpopup.SyncPopupController) used to synchronize catalogs . I want to modify this OOTB widget in order to add multiple selection instead of one (right now , you can only select one catalog at a time).
How can I achieve this ? I don't know how to extend backoffice widgets.
The Listbox you're trying to modify has an attribute called multiple. By default at initialization this is false. The widget lists (because there are 2 lists, one for stage->online and one for online->stage) doesn't have this attribute set to true when the widget is created. The initialize() method from the SyncPopupController only fill these lists with items but nothing more.
Now that you know the root of the problem, you can read this tutorial which explains you how you can extend a widget mot-a-mot. One solution could be extending the original controller and make your custom configuration in the initialize() method.
This could look like this:
public class ExtendedSyncPopupController extends SyncPopupController
{
public void initialize(Component component){
super.initialize(component);
super.getPullList().setMultiple(true);
//etc.
}
}
And after this, you can override the widget definition ( Overriding the Widget Definition chapter from the tutorial provided above ) and pass your custom controller class in <controller class="ExtendedSyncPopupController">.

Net core 2.0 - Razor Pages partial view with business itself (not MVC)

I have a sidebar view as a partial view. I want to insert it into main page.
Sidebar read some images url from database and show it into html page.
In main page, I used this code to insert sidebar:
#await Html.PartialAsync("Shared/_Sidebar")
Side bar cshtml page:
#model MyWeb.Pages.Shared._SidebarModel
...
But it raise error:
The model item passed into the ViewDataDictionary is of type 'MyWeb.Pages.IndexModel', but this ViewDataDictionary instance requires a model item of type 'MyWeb.Pages.Shared._SidebarModel'
I have research this issue, and get the answer is, must pass model from parent page, like this:
#await Html.PartialAsync("Shared/_Sidebar", Model.Urls)
If so, the parent page must handle the business of the child page. So, if I do not insert the sidebar into the main page, but to another page, I have to remove the code on the main page, and add the business code to the new page, and so on... Sidebar can not handle its own business.
In MVC, we can use RenderAction to insert a partial view with its action to handler business logic. But I have not found a way to do this in RazorPages.
Anyone help me!
There are a couple of ways including passing it as a ViewData. I found injection to be one of the cleanest ways:
Initialize your _SidebarModel as a service. This can be a scoped if you plan on using any scoped service with it (like DBContext). You can use this in your startup class:
services.AddSingleton<_SidebarModel>();
Or if you would like to initialize it here:
services.AddSingleton<>(new _SidebarModel { });
Now, instead of #model MyWeb.Pages.Shared._SidebarModel, you can use:
#inject MyWeb.Pages.Shared._SidebarModel MyModel
You can always inject and control the model from your view models as well.
You can add some basic functionality using of page view models with a class like this:
public class InjectablePage : PageModel
{
private readonly HttpContext httpContext;
public InjectablePage(HttpContext httpContext)
{
this.httpContext = httpContext;
if (httpContext.Request.Method == "GET") OnGet();
}
public virtual void OnGet() { }
}
You can extend this instead of PageModel in _SidebarModel

Register a single View as the View for Multiple ViewModels - MVVMCross

MMVMCross
Android
Windows 8
We had a View, call it FruitView displaying a ViewModel called FruitViewModel. The FruitViewModel can display lists of a particular type of fruit.
This all worked fine.
For a couple of reasons we created AppleViewModel and PearViewModel that inherit from FruitViewModel. They do not do anything, all calls are made to the base viewmodel.
I want to register the FruitView as the View for AppleViewModel and PearViewModel when I try and navigate to them using MvxNavigatingObject.ShowViewModel.
I cannot see how to override the default linking of Views to ViewModels. I read one post that suggested overriding GetViewModelViewLookup in the Setup class but that does not seem to exist. I also looked at CustomPresenters but that did not look like the right approach.
Anyone else done this?
Thanks
Pat
After spotting this question How to navigate to a ViewModel that extends an abstract class? (not one of the suggesting when i was posting) I found InitializeViewLookup that can be overridden in each platform's Setup.cs. I am augmenting the current mappings rather than replacing so have called base.InitializeViewLookup first.
protected override void InitializeViewLookup()
{
base.InitializeViewLookup();
var viewModelViewLookup = new Dictionary<Type, Type>()
{
{ typeof(AppleViewModel), typeof(FruitView) },
{ typeof(PearViewModel), typeof(FruitView) }
};
var container = Mvx.Resolve<IMvxViewsContainer>();
container.AddAll(viewModelViewLookup);
}
Thanks
Pat

MVVMCross - display view inside view

I cannot seem to find any simple examples of this.
I have a WPF UI that I wish to display a view as a child control within another view. The MvxWpfView inherits from UserControl so it should be possible, however I cannot seem to work out how to do the binding.
I get a BindingExpression path error, as it cannot find ChildView property in my ParentViewModel.
So how do I bind a view to control content?
Firstly it's possible that you just need to add the BViewModel you want displayed on AView as a property on ViewModelA
E.g.
public class AViewModel: MvxViewModel
{
public BViewModel ChildViewModel
{
get;set;//With appropriate property changed notifiers etc.
}
}
Then inside AView you just add a BView, and you can set the datacontext of BView as follows:
<UserControl DataContext="{Binding ChildViewModel}"/>
However, if you want something more flexible (and you want the presentation handled differently for different platforms) then you will need to use a Custom Presenter
Inside your setup.cs you override CreateViewPresenter:
protected override IMvxWpfViewPresenter CreateViewPresenter(Frame rootFrame)
{
return new CustomPresenter(contentControl);
}
Now create the class CustomPresenter you need to inherit from an existing presenter. You can choose between the one it's probably using already SimpleWpfPresenter or you might want to go back a bit more to basics and use the abstract implementation
The job of the presenter is to take the viewmodel you have asked it to present, and display it "somehow". Normally that mean identify a matching view, and bind the two together.
In your case what you want to do is take an existing view, and bind a part of it to the second view mode.
This shows how I have done this in WinRT - but the idea is very similar!
public override void Show(MvxViewModelRequest request)
{
if (request.ViewModelType == typeof (AddRoomViewModel))
{
var loader = Mvx.Resolve<IMvxViewModelLoader>();
var vm = loader.LoadViewModel(request, new MvxBundle());
if (_rootFrame.SourcePageType == typeof (HomeView))
{
HomeView view = _rootFrame.Content as HomeView;
view.ShowAddRoom(vm);
}
}
else
{
base.Show(request);
}
}
So what I'm doing is I'm saying if you want me to present ViewModel AddRoom, and I have a reference to the HomeView then I'm going to just pass the ViewModel straight to the view.
Inside HomeView I simply set the data context, and do any view logic I may need to do (such as making something visible now)
internal void ShowAddRoom(Cirrious.MvvmCross.ViewModels.IMvxViewModel vm)
{
AddRoomView.DataContext = vm;
}
Hopefully that makes sense! It's well worth putting a breakpoint in the show method of the presenters so you get a feel how they work - they are really simple when you get your head around them, and very powerful.

Zend Framework a common file to put functions in that can be accessed from a view

I need to have a place to put some common functions that various view scripts will use such as creating some html by passing it a variable. I know about using helpers, but I want to be able to put many functions inside it not just one helper for each function.
Is it a plugin that I need to create?
thanks
A view helper is definitively the way to go. You can group a collection of similar or related functions using a simple design pattern for your view helper:
class App_View_Helper_Example extends Zend_View_Helper_Abstract
{
/**
* #param mixed|null $var
* #return App_View_Helper_Example
*/
public function example($var = null)
{
if ($var === null) {
return $this;
}
return $this->function1($var); // shortcut to method most used
}
public function function1($var)
{
return $this->view->escape($var);
}
public function function2($var1, $var2)
{
return $this->view->escape(sprintf('%s: %d', $var1, $var2));
}
// and so on...
}
This allows you to call your helper methods in your view like this:
$this->example($var);
$this->example()->function1($var);
$this->example()->function2($var1, $var2);
I used this approach for a Google Static Map helper which provides a centered()-method to display a map centered at a given location and a byMarkers()-method that displays a static map automatically centered and zoomed around a list of given markers.
The only problem you may encounter is keeping a state in your helper across different view scripts (e.g. when using layouts or partials) as the helper will be reconstructed with every single view script. To store state across these boundaries you'll have to resort to Zend_Registry or some static member field.
Hm, 'sounds a bit smelly'. What kind of functions would these be? If your design is ok, you shouldn't have a need for this kind of dustbin class. If it is really all about view then you should create view helpers, view partials or partial loops!
Sounds like what you want is the partial helper
If you don't want to use helpers (including the partial helper) you might as well just create some global functions, stick them in some file, and include it from your bootstrap file.
If you don't want a 'bunch of helpers' (which isnt really all that bad, as other posters have suggested), you can extend Zend_View, add the member methods, then set the Viewrenderer to your extended View.
http://framework.zend.com/manual/en/zend.controller.actionhelpers.html#zend.controller.actionhelpers.viewrenderer
Thank you all for the suggestions.
I discovered that you can use a view helper (like Stefan said) to store more functions by just returning $this from it like :
class Zend_View_Helper_FormVars
{
public function formVars(){
return $this;
}
public function openFormFieldGroup($name=''){
$html='';
$html.='<div id="formFldGrpWrapper">';
$html.='<div id="formFldGrpName"><b>'.$name.'</b></div>';
return $html;
}
}
Now in my view script I can use it like this:
$formVars=$this->formVars();
$html.=$formVars->openFormFieldGroup('General');
But I'm also interested in what Justin stated that I can have a common extended view helper?
That all my views or controllers can access for doing repetative tasks like some html divs/styles, etc.... How would I go about getting that set up?
thanks.
But I'm also interested in what Justin stated that I can have a common extended view helper? That all my views or controllers can access for doing repetative tasks like some html divs/styles, etc.... How would I go about getting that set up?
In the answers you ask this additional question. My answer deals with that too.
First you need to ask yourselves why you want to have multiple helper functions in one class
One reason is that you saves you extra classes and file includes. How could you do so?
If they are related you can put them into one view helper. But don't do things like
$this->htmlWrapper()->wrapParapgraph()->wrapContentBox()
->translateFromTo('NL', 'EN');
translateFromTo(…) has nothing to with html-wrapping.
If you want to optimize your includes, you can put you common helper code into a derived View-class:
class MyView extends Zend_View
{
function wrapParagraph() {}
function otherFunction() {}
}
This option is also mentioned in the zend framework guide as a means of optimization.
Please note that view helper reusability isn't affected by the choice to create view helpers as separate classes. You automatically get access to the current view oject if your helper extends Zend_View_Helper_Abstract.
class My_View_Helper extends Zend_View_Helper_Abstract
{
function wrapParagraph($content) {
// do something …
return $this->someOtherViewHelper();
}
}
Further you wrote
$formVars=$this->formVars();
This doesn't make sense actualy, since Zend_View registers only one view helper per view isntance.
$formVars=$this->formVars();
$formVars->doOneThing();
$formVars->doSecondThing();
is equivalent to
$this->formVars()->doOneThing();
$this->formVars()->doSecondThing();
The Singleton aspect has a severe impact on the way you design view helpers as you see.