Showing posts with label WebGrid. Show all posts
Showing posts with label WebGrid. Show all posts

Wednesday, August 21, 2019

MVC Ajax WebGrid with Sorting and Paging

In this Step by step MVC Ajax WebGrid with Sorting and Paging in 10 Minutes 
   we see how to build an Ajax enabled WebGrid using an jQueryUI Theme  in 10 minutes, following this simple steps :

1) Use MVC scaffolding and build your Model and Views
2) Select a jQueryUI Theme & download it
3) In the "Index" View, replace the Table with a WebGrid and enable Ajax


All the code in this tutorial , can be downloaded from the following GitHub repository:
https://github.com/CarmelSoftware/MVC_WebGrid

This is how this sortable paged Ajax WebGrid is shown in the Ripple Mobile Emulator , Nexus Galaxy settings:


MVC Ajax WebGrid with Sorting and Paging


MVC Ajax WebGrid with Sorting and Paging in 10 Minutes


The whole process of creating an Ajax WebGrid with a jQueryUI Theme , is as following:

1) Use MVC scaffolding and build your Model and Views:

First build your MVC project using EDM & Controller scaffolding.


2) Select a jQueryUI Theme & download it

Browse to http://jqueryui.com/themeroller/  , select your Theme, and download it.
After you unzip the folder, you'll see several files in it.
You do not need all of them. Just copy the following 2 files and folder to your MVC project:
MVC Ajax WebGrid with Sorting and Paging1



Paste the files inside your MVC project as follows:

MVC Ajax WebGrid with Sorting and Paging2


As you can see, the ONLY files that we'll use from the jQueryUI theme are the following:

1) JS folder :
     "jquery-X.X.X.min.js" (here get the latest version of jQuery)
     "jquery-ui.min.js"

2) CSS folder :
     "jquery-ui.css"


Add the following references to the _Layout file:

MVC Ajax WebGrid with Sorting and Paging3

There is no need of referencing the "images" folder.
Also, you get the latest version of jQuery framework : at this moment, that version is 2.1.4


3) In the "Index" View, replace the Table with a WebGrid and enable Ajax

Then go to the "Index" view, and comment the Table that was scaffolded there.
Add the following markup to replace it:

<link href="~/Content/index.css" rel="stylesheet" />

@{ var grid = new WebGrid(Model, new[] { "Title", "DatePosted", "MainPicture" }, rowsPerPage: 3, ajaxUpdateContainerId: "gridDIV"); }


<div id="gridDIV">
@grid.GetHtml(tableStyle:"webgrid-table",headerStyle:"webgrid-header",

    columns: new[] {

        grid.Column("ID",format:(item) =>  item.GetSelectLink(item.BlogID.ToString()) ) ,
        grid.Column("Title",format:@<a href='/Blog/Comments/@item.BlogID'><b>@item.Title</b></a>),
        grid.Column("DatePosted","DatePosted", (item) => String.Format("{0:dd/MM/yyyy}", item.DatePosted != null ? item.DatePosted : DateTime.Now )),
        grid.Column("Picture",format:(item) =>
        { return new MvcHtmlString("<a href='/Blog/Comments/" + item.BlogID +
            "'><img src='/Images/"+item.MainPicture+"' style='width:100px;height:100px;'></img></a>");
        }),
  
        grid.Column(
            format:@<div class="ActionsTH">
            @Html.ActionLink("Edit", "Edit", new { id=item.BlogID })
            @Html.ActionLink("Details", "Details", new { id=item.BlogID })
            @Html.ActionLink("Delete", "Delete", new { id=item.BlogID })
        </div>)
    })
</div>

This code enable Ajax on the Grid, which comes already with Sorting and Paging functionality.
Of course, customize this code with your Model's properties.

As you can see, we also reference a "~/Content/index.css" file:
Inside this file, i added background style found in the "images" folder, such as "images/ui-bg_fine-grain" corresponding to the Theme "Pepper-Grinder" .
If you select another Theme, replace the backgrounds accordingly.
Create this CSS file in the Content folder , and paste this style in it:


body {
    background: #f7f3de url("images/ui-bg_fine-grain_15_f7f3de_60x60.png") 50% 50% repeat;
}

.webgrid-table {
    font: italic 11px Verdana;
    width: 100%;
    display: grid;
    border-collapse: separate;
    border: solid 1px #98BF21;
    background: #f8f7f6 url("images/ui-bg_fine-grain_10_f8f7f6_60x60.png") 50% 50% repeat;
    padding: 5px 5px 5px 5px;
    text-align: center;
}

.webgrid-header th {
    width: 150px;    
    background: #eceadf url("images/ui-bg_fine-grain_10_eceadf_60x60.png") 50% 50% repeat;
    color: #FFFFFF !important;
    font: 900 14px Verdana !important;
    padding: 5px 5px 5px 5px;
    text-align: center;
}

.ActionsTH {
    width: 50px;
    background: #eceadf url("images/ui-bg_fine-grain_10_eceadf_60x60.png") 50% 50% repeat;
    color: #FFFFFF !important;
    font: 900 14px Verdana !important;
    padding: 5px 5px 5px 5px;
    text-align: center;
    width: 180px;
}

.webgrid-footer, .webgrid-footer a {
    background-color: #c67f1c;
    color: #FFF;
    font: 900 14px Verdana;
    padding: 3px 3px 3px 3px;
}

.webgrid-alternating-row {
    background-color: #e5d773;
    padding: 5px 5px 5px 5px;
}

.title-column {
    font: 900 13px Verdana;
    text-align: center;
}

.webgrid-img {
    width: 150px;
    height: 150px;
}

.webgrid-table a {
    text-decoration: none;
    color: #808080;
}


Important:
If you do not see the Ajax working (), it is because the jQuery scripts are lacking.
Just cut the jQuery.js file from the _Layout file to the <head> tag :
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/jqueryui")
</head>


THE END

To use a Mobile devices Emulator, take a look at this short tutorial on installing the FREE Ripple Emulator.


That's all. Our WebGrid will be displayed this way:
MVC Ajax WebGrid with Sorting and Paging4

MVC Ajax WebGrid with Sorting and Paging5

MVC Ajax WebGrid with Sorting and Paging6





      by Carmel Schvartzman


כתב: כרמל שוורצמן



Monday, October 26, 2015

MVC Ajax WebGrid with Administrator Buttons

This article is about an MVC Ajax WebGrid with Administrator Buttons and Sorting and Paging . 
  Here we see how to build an Ajax enabled WebGrid , which in case of an User Administrator will display management buttons (Edit - Delete) , and otherwise will not.

In case of an Administrator, the WebGrid will be displayed like this:

MVC Ajax WebGrid with Administrator Buttons





In case of a common User, the WebGrid will be displayed this way:
MVC Ajax WebGrid with Administrator Buttons



All the code in this tutorial , can be downloaded from the following GitHub repository:
https://github.com/CarmelSoftware/MVC_WebGrid_Admin

This is how this Administrator's Ajax WebGrid is shown in a Mobile Emulator :

MVC Ajax WebGrid with Administrator Buttons

In the case of a common User:

MVC Ajax WebGrid with Administrator Buttons



MVC Ajax WebGrid with Administrator Buttons


The whole code for creating this Ajax WebGrid with Management functionality , can be obtained from the following GitHub rep:
https://github.com/CarmelSoftware/MVC_WebGrid_Admin


Add the following markup  to the "Index" view:

@model IEnumerable<MyGrid_BL.Blog>

@{
    ViewBag.Title =  "Ajax WebGrid with Administrator Role Check";
    WebGrid grid = new WebGrid(Model, new[] { "Title", "Text", "DatePosted", "MainPicture", "Blogger" },
        rowsPerPage:2,ajaxUpdateContainerId:"GridDiv");

    IEnumerable<WebGridColumn> oColumns = new[] {

        grid.Column("ID",format:(item) =>  item.GetSelectLink(item.BlogID.ToString()) ) ,
        grid.Column("Title",format:@<a href='/Blog/Details/@item.BlogID'><b>@item.Title</b></a>),
        grid.Column("DatePosted","DatePosted", (item) => String.Format("{0:dd/MM/yyyy}", item.DatePosted != null ? item.DatePosted : DateTime.Now )),
        grid.Column("Picture",format:(item) =>
        { return new MvcHtmlString("<a href='/Blog/Details/" + item.BlogID +
            "'><img src='/Images/"+item.MainPicture+"' style='width:100px;height:100px;'></img></a>");
        })
    };

    if (User.IsInRole("Admin"))
    {
        oColumns = oColumns.Concat(new[] {grid.Column(
            format:@<div class="ActionsTH">
            @Html.ActionLink("Edit", "Edit", new { id=item.BlogID })<br />
            @Html.ActionLink("Details", "Details", new { id=item.BlogID })<br />
            @Html.ActionLink("Delete", "Delete", new { id=item.BlogID })
        </div>) });
    }
    
}

<h2>@ViewData["Title"]</h2>

<div id="GridDiv">
    @grid.GetHtml(tableStyle:"webgrid-tableStyle",headerStyle:"webgrid-headerStyle",footerStyle:"webgrid-footerStyle",alternatingRowStyle:"webgrid-alternatingRowStyle",columns: oColumns) </div>
<p style="text-align:center;">
     
    <input type="button"   value="Create New" onclick="javascript:location='/Blog/Create'" class="btn btn-default"/>
</p>



This code enable the Management Buttons on the Grid, only in case of a Power User such as an Administrator.

The code to set some User to the "Admin" Role, must be added to the "Acount" Controller, at the Register Action, and is as follows:

[HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    if (!Roles.RoleExists("Admin"))
                    {
                        Roles.CreateRole("Admin");
                    }
                    WebSecurity.CreateUserAndAccount(model.UserName, model.Password);

                    string sAdmins = ConfigurationManager.AppSettings["Admins"];
                    string[] oAdmins = sAdmins.Split(';');

                    WebSecurity.Login(model.UserName, model.Password);

                    foreach (string sAdmin in oAdmins)
                    {
                        if (string.Compare(model.UserName, sAdmin) == 0
                                                &&
                            !Roles.IsUserInRole("Admin"))
                        {
                            Roles.AddUserToRole(model.UserName, "Admin");
                        }
                    }



                    return RedirectToAction("Index", "Home");
                }
                catch (MembershipCreateUserException e)
                {
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

And these are the AppSettings to the Web.config file:


<appSettings>
    <add key="Admins" value="sa;sa1;sa2;sa3"/>
  </appSettings>

As you can see, we also reference a "~/Content/WebGrid.css" file:


body {
    background: #f7f3de url("images/ui-bg_fine-grain_15_f7f3de_60x60.png") 50% 50% repeat;
}

.webgrid-tableStyle {
    font: italic 11px Verdana;
    width: 100%;
    display: grid;
    border-collapse: separate;
    border: solid 1px #98BF21;
    background: #f8f7f6 url("images/ui-bg_fine-grain_10_f8f7f6_60x60.png") 50% 50% repeat;
    padding: 5px 5px 5px 5px;
    text-align: center;
    border-radius:10px;
}

.webgrid-headerStyle th {
    width: 250px;    
    background: #c67f1c url("images/ui-bg_fine-grain_10_eceadf_60x60.png") 50% 50% repeat;
    color: #FFFFFF !important;
    font: 900 14px Verdana !important;
    padding: 5px 5px 5px 5px;
    text-align: center;
    height:50px;
}

.ActionsTH {    
    background: #eceadf url("images/ui-bg_fine-grain_10_eceadf_60x60.png") 50% 50% repeat;
    color: #FFFFFF !important;
    font: 900 14px Verdana !important;
    padding: 5px 5px 5px 5px;
    text-align: center;
    width: 180px;
}

.webgrid-footerStyle, .webgrid-footerStyle a {
    background:#c67f1c url("images/ui-bg_fine-grain_10_eceadf_60x60.png") 50% 50% repeat;
    color: #FFF;
    font: 900 14px Verdana;
    padding: 3px 3px 3px 3px;
    height:50px;
}

.webgrid-alternatingRowStyle {
    background: #f8f7f6 url("images/ui-bg_fine-grain_10_f8f7f6_60x60.png") 50% 50% repeat;
    padding: 5px 5px 5px 5px;
}

.title-column {
    font: 900 13px Verdana;
    text-align: center;
}

.webgrid-img {
    width: 150px;
    height: 150px;
}

.webgrid-tableStyle a {
    text-decoration: none;
    color: #808080;
}
select {
      width: 200px;
    }


Important:
If you do not see the Ajax working  , it can be because some jQuery scripts are missing.
Just cut the jQuery.js file from the _Layout file to the <head> tag :
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/jqueryui")
</head>



To install a Mobile Emulator, take a look at this tutorial on installing the FREE Ripple Emulator.


That's all. Our Administrator WebGrid will be displayed this way:

MVC Ajax WebGrid with Administrator Buttons

MVC Ajax WebGrid with Administrator Buttons






      by Carmel Schvartzman


כתב: כרמל שוורצמן


Thursday, June 5, 2014

Step by Step how to create a WebGrid with Grouping functionality

In this tutorial we'll learn how to create a WebGrid with Grouping support and JQuery UI Accordion enhancement. The Grid will expose data dynamically loaded from database and sent by the Action method from the web server, and will offer Grouping functionality in the shape of a JQueryUI Accordion.
We'll want to create a webgrid with Grouping functionality , showing as follows:



Let's say you have two related tables, connected by a ONE-TO-MANY relationship as follows:

For the sake of Grouping, we'll create an "Intersection Entity" that represents an INNER JOIN between the tables:
As you see, the new Entity just joins the records of the 2 tables. After you built that class in the Model's folder, create a new Controller:




Inside the Controller, code an Action method which JOINS the two tables in an anonymous class:

Then, for each record you fetch, create an Intersection Entity record as well:

public ActionResult Index()
        {
            List<PostComments> comments = new List<PostComments>();
            using (BlogEntities ctx = new BlogEntities())
            {
                var list = (from p in ctx.Blogs
                            join c in ctx.Comments
                            on p.BlogID equals c.BlogID
                            select new
                            {
                                p.BlogID,
                                PostTitle = p.Title,
                                p.MainPicture,
                                c.CommentID,
                                CommentTitle = c.Title,
                                c.Text
                            }
                        ).ToList();
                foreach (var item in list)
                {
                    comments.Add(new PostComments(item.BlogID, item.PostTitle,
                        item.MainPicture, item.CommentID, item.CommentTitle, item.Text));
                }
            }
            return View(comments);
        }
Next, add a View to display the List<>:



Inside the View, add a <div> and an FOREACH clause which runs over a GROUP BY some relevant DISTINCT field, such as the Title :

As you can see, for EACH different Post, we create a <TABLE> with the Title and the Picture of it. And then, we add ANOTHER bucle which appends a new row to the table, for each Comment the Post has:

The whole Grid markup should appears as follows:

<div id="divPosts">
    @{
        foreach (var post in Model.GroupBy(p => p.PostTitle).Select(p => p))
        {
        <h1>@post.Key </h1>
        <div>
            <table>
                <tr>
                    <th>Title </th>
                    <th>Comment </th>
                    <th><img src="Images/@post.First().Image" /></th>
                   
                </tr>
                @foreach (var comment in @post)
                {
                    <tr>
                        <td>
                            @Html.DisplayFor(modelItem => comment.CommentTitle)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => comment.CommentText)
                        </td>                      
                        <td>
                            @Html.ActionLink("Edit", "Edit" )
                            @Html.ActionLink("Details", "Details" )
                            @Html.ActionLink("Delete", "Delete" )
                        </td>
                    </tr>
                }
            </table>
        </div>
        }
    }
</div>

Now, as you can see, we put each GROUP inside a new <div> nested inside an outer <div>. This is for using the Accordion: add the following <script>:


<style>
    th {
        text-align: center;
    }
    td img, th img {
        width:100px;height:100px;
    }
</style>
<script>
    $(function () {
        $("#divPosts").accordion({
            heightStyle: "content"
        });
    });
</script>

Also, we'll need some CSS to properly display the data. We added an JQuery UI Theme to the bundles in the App_Start BundleConfig.cs file:


Of course, we load those CSS files and JQUERY scripts in our _Layout file:


Build and launch the web app, to see the following display:



The user can see the different Posts with its respective Comments, clicking the Accordion titles:





That's all!! 
In this tutorial we've learn how to create a WebGrid with Grouping functionality and JQuery UI Accordion enhancements.  

Happy programming.....
        By Carmel Schvartzman
כתב: כרמל שוורצמן

Sunday, June 1, 2014

Step by Step how to create an Ajax enabled Master-Details WebGrid using a Child Action and a Partial View

        By Carmel Shvartzman


In this tutorial we'll learn how to create an Ajax enabled Master-Details WebGrid using a Child Action and a Partial View  . The parental Grid will expose data dynamically loaded from database and sent by the Action method from the web server, and will offer CRUD (Create Retrieve Update Delete) functionality. Also, the Grid will send Ajax requests for paging, sorting and displaying related data in a Details <TABLE>  grid.
The Details WebGrid will fetch the Comments for the selected Posts, and will be served by a Child Action, where we could insert some Application logic and filter the data.
The webgrid will also redirect the user to another web page exposing all comments for a selected Post, web page which will use the same Partial View we're Ajax rendering in the Index web page as a Details table.
We'll want to create a Master-Details webgrid with CRUD functionality , showing as follows:


The style you see comes from a free CSS Template, that can be easely added to your application, as we already explained in this tutorial.

This tutorial will use data fetched from the Entity Framework, exposing the following classes:


For each Blog Post selected in the Master webgrid, we'll display all the related Comments in a subsidiary Details grid.

To create the Master WebGrid we must create our own View, and it will not be difficult if we take advantage of the Scaffolding capacities of the MVC environment. So first let's create a new Controller called "BlogController", automatically creating the necessary Views to cope with the CRUD functionality requirements. So right click over the Controllers folder, and add a new Controller:



Name it "BlogController", and select the template "MVC Controller with read/write actions and views, using Entity Framework":



The Context to use will be of course the one you named while creating your Entity Framework Data Model, and the Model will be the Blog class, because we'll be creating, updating and deleting Blog objects.
After you create the Controller, open it and take a look at the Action Methods created for you: there are action methods for displaying the list of Blog posts (Index method), to create new ones , to update them, and to delete:




Open the Views folder and see the Views that were created for you:



First of all, let's add a link inside the _Layout .cshtml file Menu, in order to browse to the Blog web page from the Home page:

We also add the Scripts.Render calls at the <header> of the _Layout file, in order to load the necessary jquery and CSS files:




Delete the @Scripts.Render("~/bundles/jquery") from the <footer> of the file:


If you want to perform more Ajax calls using @Ajax.ActionLink() , add also a reference to the "jqueryval" bundle: @Scripts.Render("~/bundles/jqueryval") :



Next, we'll need two new Actions in the Blog Controller:
1) a Comments Action method: for rendering the _PostComments template as a View
      at the url "/Blog/Comments/{ID}". You don't need to create a View for this Action method:




2) a DetailsGridComments Child Action method: for rendering the _PostComments  template as a Partial View while performing an Ajax call:


To create the Partial View, open the View's dialog and type the following:


Keep in mind we will use this Partial View as such, inside the Index View, and also as a regular View as the "Comments" View .
Inside the Partial View we got, there are two code areas automatically created, but which we don't need: the "Create" link and the "Edit" buttons, so delete it:



Also, customize the <table> as follows :


We want a WebGrid with paging-sorting capabilities,  instead of a table. So we'll replace the <TABLE> ta g at the Index file with an WebGrid Html Helper: open the Index View:





And comment the whole  <table> tag:



Next, we'll instantiate a WebGrid, using an overload of the extension method with the following parameters:







Back to the Index View,  create a <DIV> enclosure for the WebGrid to be Ajax replaced, and type the final code for the WebGrid  setting as its arguments the data included in the Model, the number of rows to display in each page (2) , and the container to be updated by the Ajax requests :




@{
    ViewBag.Title = "Index";
    WebGrid grid = new WebGrid(Model, rowsPerPage: 2, ajaxUpdateContainerId: "gridDIV");
}


Now we display the markup of the WebGrid using the GetHtml() WebGrid method,  and formatting the   picture field. Also we set the "BlogID" column as the one acting as the SELECTOR that will be clicked by the user in order to Ajax-load all related Comments:



Also, we set the other three columns as hyperlinks to take the user to a "Comments" web page exposing all the comments for a selected Post. We do that using the "format:" parameter, in two ways:
1) we render directly the markup with the <a> tag
2) we return an MvcHtmlString object representing the hyperlink, and enclosing the picture: clicking the    picture will take the user to the "Comments" web page:





We automatically got the paging and sorting WebGrid functionalities. We also got all CRUD functionality that was there before: deleting, editing , and so, by copying the CRUD block that you commented before(inside the <table> tag):







Now return to the Index View, to add the code that will display the Partial View. What we do is to check that some row has been selected in the WebGrid, and then we fetch the selected row, in order to get the ID of the chosen Post.
If the row is not null, we send that ID to a Child Action using the RenderAction() function and that way we got all related comments for that post:



The code (to copy-paste) is the following:

<div id="gridDIV">
@{
     
    @grid.GetHtml(columns: new[] {

        grid.Column("ID",format:(item) =>  item.GetSelectLink(item.BlogID.ToString()) ) ,
        grid.Column("Title",format:@<a href='/Blog/Comments/@item.BlogID'><b>@item.Title</b></a>),
        grid.Column("Text",format:@<a href='/Blog/Comments/@item.BlogID'><i>@item.Text</i></a>),
        grid.Column("Picture",format:(item) =>
        { return new MvcHtmlString("<a href='/Blog/Comments/" + item.BlogID +
            "'><img src='/Images/"+item.MainPicture+"' style='width:100px;height:100px;'></img></a>");
        }),
 
        grid.Column(format:@<td>
            @Html.ActionLink("Edit", "Edit", new { id=item.BlogID })
            @Html.ActionLink("Details", "Details", new { id=item.BlogID })
            @Html.ActionLink("Delete", "Delete", new { id=item.BlogID })
        </td>)
    })
    if (grid.HasSelection )
    {
        MvcApplication1.Models.Blog post = grid.Rows[grid.SelectedIndex].Value;
        Html.RenderAction("DetailsGridComments", new { id = post.BlogID });
    }
     
}
</div>



Notice that we get the VALUE of the selected row as a "Blog" object and NOT as a WebGridRow. Save the project and refresh the browser:




Notice that you got all Paging-Sorting functionalities in an Ajax enabled mode. Now , if you click the ID field you get all the Comments as Ajax request:






We got all the Comments for that post. Now let's try the other Hyperlinks we added, clicking for example the Title or the Picture of some Post:




We are then redirected to the Comments web page, to see all Comments for the selected Post:



In this tutorial we've learned how to create an Ajax enabled Master-Details WebGrid using a Child Action and a Partial View .  
That's all!! 
Happy programming.....


כתב: כרמל שוורצמן