Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create a partial view as independent "widget"?

With old ASP.NET we could create User controls(.ascx) easily, in fact many controls were/are fully independent from the current View. I wonder if the same is possible with MVC?

I need to display simple list with users, problem is - this list should be displayed in more then one places on my site. While I can simply modify my views models, and add model of the "widget" to them, I would like to avoid this. Preferably I would like my users list to require only the following:

@Html.Partial("Link/To/My/List")

to be included in other View - list's model would have to be populated some other way. I thought to use AJAX inside my partial but this seems like a bad idea. Is there any other way around it or is it simply a bad idea that breaks MVC assumptions?

like image 886
user2384366 Avatar asked Nov 15 '25 23:11

user2384366


2 Answers

You can use the RenderAction method to render a Partial view. The partial view can be associated with a Model that is different from the calling page's Model

Calling the action method from the View

@{Html.RenderAction("SomeAction", "SomeController");} 

Action method returns the partial view

public ActionResult SomeAction()
        {
            //Construct SomeModel here..  
            return PartialView("SomeView", SomeModel);
        }
like image 191
Praveen Reddy Avatar answered Nov 17 '25 20:11

Praveen Reddy


You can write partial views that are encapsulated "widgets" by embedding a script block inside the partial view. Wrapping a script block inside a div is one clean way to wrap the markup and the initialization script together in a partial view widget. For example, I might have a partial view named "_WidgetPartial" that I use throughout my site. If I place in two places on my master page it should just work and I prefer not to have to write logic in my master page to initialize the widget.

You might want to write the widget as a jQuery plugin of some sort and then the script block becomes a simple one liner to initialize it. The partial view looks something like...

<div id="widgetWrapper">

    <ul class="widget">
    </ul>

    <script>
        $(document).ready(function() {
            $("ul.widget").widget(...);
        });
    </script>
</div>

If you will never use it more than once in a page, its simple, otherwise, wrap the code so it doesn't execute twice. See below. For the sake of Stack Overflow snippets I simulate it by repeating the partial view twice in the code snippet to represent including a partial view widget twice in a master page.

My master page might look like:

<div id="left-nav">
   @Html.Partial("_WidgetPartial")           
</div>

<div id="body">
</div>

<div id="right-nav">
   @Html.Partial("_WidgetPartial")
</div>

Example:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<!-- Self-contained partial view containing widget -->

<div id="widgetDiv" class="panel panel-default">

    <div class="panel-heading">Event Dates</div>
    <div class="panel panel-group">
       <ul class="widget">
         <!-- These will load dynamically -->
       </ul>
    </div>

    <script>
        $(document).ready(function() {

            // Run this once only in case widget is on page more than once
            if(typeof $widget == 'undefined') {
                $widget = $("ul.widget"); // could be more than one
                // mock data to simulate an ajax call
                var data = [
                   {Description: "March", StartDate: "03/01/2015"},
                   {Description: "April", StartDate: "04/01/2015"},
                   {Description: "May", StartDate: "05/01/2015"}
                ];

                $.each($widget, function(w, widget) {
                    // might be an $.ajax call
                    $.each(data, function(i, row) {
                        $(widget).append("<li><a href='/Widget/Search?startDate=" + row.StartDate + "'>" + row.Description + "</a></li>");
                    });
                });
            }
        });
    </script>
</div>
<!-- End of widget / partial view -->



<!-- Second copy of above for sake of example snippet -->
<!-- No need to read further -->









<!-- Self-contained partial view containing widget -->

<div id="widgetDiv" class="panel panel-default">

    <div class="panel-heading">Event Dates</div>
    <div class="panel panel-group">
       <ul class="tinylist nav nav-sidebar widget">
         <!-- These will load dynamically -->
       </ul>
    </div>

    <script>
        $(document).ready(function() {

            // Run this once only in case widget is on page more than once
            if(typeof $widget == 'undefined') {
                $widget = $("ul.widget"); // could be more than one
                // mock data to simulate an ajax call
                var data = [
                   {Description: "March", StartDate: "03/01/2015"},
                   {Description: "April", StartDate: "04/01/2015"},
                   {Description: "May", StartDate: "05/01/2015"}
                ];

                $.each($widget, function(w, widget) {
                    // might be an $.ajax call
                    $.each(data, function(i, row) {
                        $(widget).append("<li><a href='/Widget/Search?startDate=" + row.StartDate + "'>" + row.Description + "</a></li>");
                    });
                });
            }
        });
    </script>
</div>
<!-- End of widget / partial view -->
like image 33
codenheim Avatar answered Nov 17 '25 22:11

codenheim