I have a view that renders a form with code similar to the following:
#using( var form = Bootstrap.Form().SetHorizontal( 3 ).AddCss( Css.ColSm8, Css.ColMdOffset2 ).Begin() )
{
#form.DisplayFor( m => m.Name )
// bla bla bla
#Html.Action( "Details", "Fare", new { entity = Model.FareId } )
}
How can I access the form object in the partial view, so that the same layout is applied to the whole form?
A lot of work was spent ensuring that the Bootstrap control stack would carry-over into partial views. You have two options here:
The first is to just pass the form object to the partial/action as part of the model. In your case, you would just add it as another property in the anonymous model object you're sending to the action.
You don't need to use the form instance to make FluentBootstrap recognize you're in a form. It's just a convenience to make calling the extensions appropriate to a form easier. You can also just call something like Bootstrap.DisplayFor(x => x.Name) right from the global Bootstrap object in your partial and it will respect any settings you've placed in the containing form defined in the containing view.
Related
In the shop's customer section I would like to render the user account menu (which we can see by default when reaching /my-account URL) as a side column on some others controllers like the ones associated to "/my-adresses", "/identity" pages ..
I thought I would have to create another controller which purpose would be to gather menu infos and only render the menu <ul> list. Then I could override Controllers such as MyAccountController, IdentityController to include this former Ctrl and then render its content as part of the views of those two other controllers views.
So how one can load a specific controller from another in order to render shared views between pages ? Which is the right/clean way to do that ?
I heard about $this->getController() but I did not find any snippet or implementation of what I'd like to achieve. I new to Prestashop but even if the code seems clear, I don't get the point here.
Thank you !
After getting a bit deeper into sources, I ended up moving the menu (initially part of the MyAccountControllerCore alias my-account template) into a brand new Controller "MyAccountMenuController", in /override/controllers/front/.
<?php
// In /override/controllers/front/MyAccountMenuController.php
// The "exposer" controller
public function display()
{
// Do what ever you want to pass specific variables
if (! $this->template) {
throw new Exception(get_class($this) . '::display() : missing template.');
}
$this->context->smarty->display($this->template);
return true;
}
I am now able to import this menu by adding the following snippet inside the initContent() method of each controller that are part of the customer account section (this means that each of them must be overridden, for more info about overriding controllers, see documentation):
<?php
// In /override/controllers/front/MyAccountController.php
// The "consumer" controller
public function initContent() {
// ...
// Importing the customer area's menu
$menuController = $this->getController('MyAccountMenuController');
ob_start();
$menuController->run();
$this->context->smarty->assign('myAccountMenu', ob_get_clean());
}
I don't think the original purpose of getController method (located in ControllerCore class) was meant to include another controller output, at least in Prestashop 1.5. Still, to me this approach is far cleaner than duplicate views code.
If you have a better (cleaner) approach to implement such a mechanism, please let me know !
Any thoughts ?
How do I post from one controller into another view?
I have a Review model and a Product model. The Review form is displayed in the Product view through a widget, but how do I submit the form itself? Right now, it doesn't do anything. I can submit through review/create, but not through the Product View.
Or am i suppose to do the post in the widget?
You can achieve it if you put code like below on components/ReviewWidget.php . I supposed you have Review as model and its respective controller and views file on default locations.
<?php
class ReviewWidget extends CWidget{
public function init() {
return parent::init();
}
public function run(){
$model = new Review;
if (isset($_POST['Review'])) {
$model->attributes = $_POST['Review'];
$model->save();
}
$this->renderFile(Yii::getPathOfAlias('application.views.review'). '/_form.php',array(
'model' => $model,
));
}
}
Then, call above widget on any where on view like below ,
<?php $this->widget('ReviewWidget'); ?>
It will handle item creation only. You have to create code to item update by yourself.
In your controller action you must use function renderPartial
$this->renderPartial('//views/reviw/_form',array('data' => $data ) );
First argument of this function is used to determine which view to use:
absolute view within a module: the view name starts with a single slash '/'. In this case, the view will be searched for under the
currently active module's view path. If there is no active module,
the view will be searched for under the application's view path.
absolute view within the application: the view name starts with double slashes '//'. In this case, the view will be searched for
under the application's view path. This syntax has been available
since version 1.1.3.
aliased view: the view name contains dots and refers to a path alias. The view file is determined by calling
YiiBase::getPathOfAlias(). Note that aliased views cannot be themed
because they can refer to a view file located at arbitrary places.
relative view: otherwise. Relative views will be searched for under the currently active controller's view path.
Also you can use this function in your views. But the most convenient way to reuse views is to create widgets.
I have a page for listing items, and I have anchors in each of the items to edit it.
So when I click on the edit link, it will take me to the edit page, which have save button and cancel button.
I want it when I click the save button it'll take me to confirmation page which have OK and cancel button.
I know in asp.net mvc you can send model into the view by this
return View("Edit", model);
It is sensible to then write each of the model property like this in the view
#Html.EditorFor( model => model.name )
#Html.EditorFor( model => model.description )
//more properties here...
So that after I click the save button, I can have the model back in the controller
But after the edit page, I only need to view a question in the confirmation page do I have to write it manually like this
#Html.HiddenFor( model => model.name )
#Html.HiddenFor( model => model.description )
//more properties here...
Is there a one line hassle free function to do this in asp.net mvc?
You can use #Html.EditorForModel() helper. However this method will produce default UI elements like textboxes. You can provide a custom template that will produce hidden inputs.
I use Caliburn.Micro for my Silverlight application.
I have a view/viewmodel to create a new Item.
On the view there is one combobox.
The first time I open the view , fill in all fields, the Item is saved correctly.
The second time I open the view, fill in all fields, all teh values of them are changed in the object, except the value of the combobox, this property of Item stays 0 (it's an integer).
Any ideas why this is? I think the Caliburn framework is doing something weird.
thanks,
Filip
The code to open the view was:
EventAggreg.EventAgg.Publish(new ObjectDetailEvent() { ObjectDetail = new ObjectDTO() });
I replaced it with:
EventAggreg.EventAgg.Publish(new ObjectDetailEvent() { ObjectDetail = new ObjectDTO { LandId = 0 } });
LandId is the property bound to the combobox.
So when this is filled in by default, teh notify works perfect every time.
Here is what I'd like to do :
I have an Silverlight application using navigation frame and MEF. (like this one : http://msdn.microsoft.com/en-us/magazine/gg535672.aspx)
This application consists of a set of buttons. Each button click load a view and its associated ViewModel.
Within theses views, I've a list with items and when I click on each items it refreshs a kind of sub-view in this view.
I'd like to create a navigation system : for example myapp.aspx#view1/2, where 2 is in fact the item clicked in the list. If I click on one of the button, it would load a default item and refresh all the view, but when I click on an item, I wouldn't like to refresh all the view but only certain part of the view (I do not want to create another instance of the view and viewmodel).
My problem is in fact that I would like to get the best pratice to get a reference to an existing view or viewmodel when i'm navigating to this page that has already been loaded (for example from myapp.aspx#view1/2 to myapp.aspx#view1/3)(I plan to do this into the BeginLoad of the ContentLoader class)
If I get the viewmodel, I can do that I want by changing for example the current itemId property which could refresh the view thanks to binding.
Thanks in davance if you have something to propose.
A common approach is to use some form of Messenger to do this type of operation. The item's click could trigger the sending of a message, with the Item attached. The ViewModel in question would be a subscriber, and edit its current settings (ie: it's ItemId, which would trigger the binding refresh).
The most common implementations are usually ones similar to the Messenger service in MVVM Light.
It's fairly easy to roll your own here, though, especially since you're already using MEF. Just create a service to handle the message passing, and import it into both endpoints.
Actually, I would have prefered to use an URI to navigate in my application when I click on an item, but if I use an URI, the entire view is reloading and not the specific part I'd like to.
With the messenger, I won't be able to use navigation with url within the view, I think ? Or else I didn't really figure out what you proposed to me.
The algorithm I would like to take is :
navigate("...asp#MyView1/1")
MyView1 is current view ?
yes then I'd like to get the viewmodel of the current view and change it the ItemId property with 1
no, then the view will be created
And I'd like to implement this algorithm there : (this is the place where the view is instancied for each navigation, in my CompositionNavigationContentLoader class)
public IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback, object asyncState)
{
// Convert to a dummy relative Uri so we can access the host.
var relativeUri = new Uri("http://" + targetUri.OriginalString, UriKind.Absolute);
// Get the factory for the ViewModel.
var viewModelMapping = ViewModelExports.FirstOrDefault(o => o.Metadata.Key.Equals(relativeUri.Host, StringComparison.OrdinalIgnoreCase));
if (viewModelMapping == null)
throw new InvalidOperationException(
String.Format("Unable to navigate to: {0}. Could not locate the ViewModel.", targetUri.OriginalString));
// Get the factory for the View.
var viewMapping = ViewExports.FirstOrDefault(o => o.Metadata.ViewModelContract == viewModelMapping.Metadata.ViewModelContract);
if (viewMapping == null)
throw new InvalidOperationException(
String.Format("Unable to navigate to: {0}. Could not locate the View.", targetUri.OriginalString));
// Resolve both the View and the ViewModel.
var viewFactory = viewMapping.CreateExport();
var view = viewFactory.Value as Control;
var viewModelFactory = viewModelMapping.CreateExport();
var viewModel = viewModelFactory.Value as IViewModel;
// Attach ViewModel to View.
view.DataContext = viewModel;
viewModel.OnLoaded();
Thanks.