widgets, .cshtml, and themes

Topics: Customizing Orchard, Writing themes
Aug 19, 2011 at 1:34 AM

I'm brand new to Orchard and to MVC 3, so naturally I've got an issue I can't quite figure out. I've overriden the Search.SearchForm widget in my theme, and have made it look and behave exactly like I want it to look. I can add the widget via the Admin site to a zone, and everything is fine. It looks like it should and behaves like it should.

What I really want to do though, is embed the search form in a specific spot directly in my Layout.cshtml file without having to "enable" it via the Admin site. I know that to make it work, search indexing and Lucene have to be enabled, but assuming that's done, how do I (or can I), in my Layout.cshtml, embed the Search.SearchForm widget as if it were a partial view?

Basically, the code in the Layout.cshtml file is:

<div id="status" class="inherit-bg">
        <div class="page-center">
            <ul id="nav">
                <li><a href=".">Store</a></li>
                <li><a href=".">Bike Shop</a></li>
                <li><a href=".">Train</a></li>
                <li><a href=".">About</a></li>
            </ul>
            CODE TO EMBED WIDGET WOULD BE HERE
        </div>
    </div>
</div> 

Can someone provide some guidance for what seems to be a fairly simple problem? Assuming it's straightforward, I'm just not sure if my problem is with my knowledge of Orchard and its implementation of widgets or if it's due to my lack of knowledge of MVC 3 and using .cshtml files.

Coordinator
Aug 19, 2011 at 4:40 AM

It's quite simple as this specific widget only contains a form to the Search controller. So Add the widget and copy paste the html it generated. Then you can remove it. Also, you can have your Theme to enable specific modules automatically when it's installed. In the Theme.txt file, add a "Dependencies: Orchard.Search, Lucene: line, and it should do it.

Aug 19, 2011 at 4:57 AM

But then if I need to change the search widget, I have to make the changes in two places - the overriden view (Search.SearchModel in my theme) as well as where I put the "static" version of the search bar. is that correct?

Thanks for the tip on adding the dependencies.

Coordinator
Aug 19, 2011 at 5:06 AM

Well there is no way to add a "widget" from a template. And also, what would you change in the search widget ... there is absolutely nothing that can be changed ;) but the title.

Coordinator
Aug 19, 2011 at 5:08 AM

Another "clean" solution would be to create a Zone in your layout, where you want to put this widget, then add the widget by code, using a Migration class in a Theme project file. Then you will really add a widget, than you can even remove later, through the admin. This is how I would do it.

Aug 19, 2011 at 5:14 AM

I may not be stating things correctly when I said I changed the search widget. I added a Parts/Search.SearchForm.cshtml file in my Views folder, and then added some JavaScript to create an initial value (in my case, the string 'Search...') that is cleared when the text box gets focus. If the text box loses focus and the search text box is empty, I replace the initial value.

I think my other option is to create a "Search" zone, place the generated HTML there (and JavaScript), and then use the @Display(MY_SEARCH_ZONE_NAME) to display it.

My initial expectation was that I could effectively add my Search.SearchForm.cshtml file to another .cshtml file via a similar mechanism to a partial view.

Aug 19, 2011 at 1:48 PM

If all you want to do is override the Search form widget's template, and it sounds like you've already done that, why not just use the admin UI to put the widget in whatever zone you want? You can define a Zone in Layout.cshtml right where you intend to put it, define that Zone name in your Theme.txt file, then you can use the widget UI to place it there. The advantage you get with this is that you can also use a Layer rule to control _when_ it shows up, not just _where_ it shows up (and if you don't care when, then just use the Default layer).

If you don't care about when it shows up and really just want to hard code it in your layout like you're describing, you can probably do it by just asking it to display that shape. See Betrand's two blog posts here for some ideas on doing that:

http://weblogs.asp.net/bleroy/archive/2011/06/30/creating-shapes-on-the-fly.aspx
http://weblogs.asp.net/bleroy/archive/2011/06/30/so-what-are-zones-really.aspx

Aug 19, 2011 at 2:50 PM

Could I see an example that works with the Search form? I'm struggling to understand the context from where I can grab it and @Display it.

Aug 19, 2011 at 4:06 PM

Okay, so in your theme you should have Views/Parts.Search.SearchForm.cshtml (or alternatively, Views/Parts/Search.SearchForm.cshtml - either way should work). That's the search form widget that you copied from the Search module and modified with your own code.

Remember, that will override the default Search Form widget if you just use the widget UI for placing it in a Zone, which you could do like this in your Layout.cshtml:

<div id="status" class="inherit-bg">
        <div class="page-center">
            <ul id="nav">
                <li><a href=".">Store</a></li>
                <li><a href=".">Bike Shop</a></li>
                <li><a href=".">Train</a></li>
                <li><a href=".">About</a></li>
            </ul>
            @Zone(Model.Search)
        </div>
    </div>
</div>

Just add "Search" to the list of zones in your Theme.txt and you're good to go. But I realize you're trying to display it directly from Layout instead. :-)  So here's how you can do that:

<div id="status" class="inherit-bg">
        <div class="page-center">
            <ul id="nav">
                <li><a href=".">Store</a></li>
                <li><a href=".">Bike Shop</a></li>
                <li><a href=".">Train</a></li>
                <li><a href=".">About</a></li>
            </ul>
            @Display.Parts_Search_SearchForm()
        </div>
    </div>
</div>

Aug 19, 2011 at 5:11 PM

Got it! Thanks much!