2

I have a page with a video at the top and a list of videos you can choose from. Currently, clicking a link in the video list will reload the entire page. I need it to only refresh the partial view I have containing the video at the top of the page.

I saw several posts here on SO showing how to reload partial views with JQuery, but couldn't get it to work correctly in my situation. I'm unsure how to pass the correct id of the video along.

Controller:

    public ActionResult Videos(int topVideo = 0)
    {
        VideosModel model = new VideosModel();
        model.Videos = StatsVideoService.GetEntityList(new Lookup(TableStatsVideo.IsDeleted, false)).OrderByDescending(x => x.DateCreated).ToList();

        if (topVideo == 0)
            model.TopVideo = model.Videos.First();
        else
        {
            model.TopVideo = model.Videos.Where(x => x.StatsVideoId == topVideo).FirstOrDefault();
            if (model.TopVideo == null)
                model.TopVideo = model.Videos.First();
        }

        return View(model);
    }

View:

@model Project.Models.VideosModel

<section class="videos">
    <div id="top_video">
        @{Html.RenderPartial("StatsVideo", Model.TopVideo);}
    </div>

    <ul>
        @foreach (var item in Model.Videos)
        {
            <li>
                <div class="videoList">
                    <a href ="@Url.Action("Videos", "Home", new { topVideo = item.StatsVideoId })">
                        <img src="@Url.Content("~/Content/img/video-ph.png")" />
                    </a>
                    <p class="videoTitle">@item.Title</p>
                </div>
            </li>
        }
    </ul>
</section>

If there's any more information needed, please let me know.

3 Answers 3

3

After several hours of bashing my head against the wall, I got it to work! Just as a reference to anyone else in the future who's viewing this article, here's how I got it to work:

I set the onclick of the link to point to a javascript method, passing in the id of the video as a parameter:

    @foreach (var item in Model.Videos)
    {
        <li>
            <div class="videoList">
                <a href ="#" onclick="updateTopVideo(@item.StatsVideoId)">
                    <img src="@Url.Content("~/Content/img/video-ph.png")" />
                </a>
                <p class="videoTitle">@item.Title</p>
            </div>
        </li>
    }

And then I included this script in the view at the bottom:

<script>
    var updateTopVideo = function (itemId) {

        var url = '@Url.Content("~/Home/StatsVideo/")';
        url = url + itemId;
        $.get(url, "", callBack, "html");
    };

    var callBack = function (response) {
        $('#top_video').html(response);
    };
</script>

Finally, I added a method to my controller that would return the partial view needed for the video at the top of the screen:

    public ActionResult StatsVideo(int Id)
    {
        IStatsVideo vid = StatsVideoService.GetEntity(new Lookup(TableStatsVideo.StatsVideoId, Id));
        if (vid == null)
            vid = StatsVideoService.GetEntityList(new Lookup(TableStatsVideo.IsDeleted, false)).OrderByDescending(x => x.DateCreated).FirstOrDefault();

        return PartialView(vid);
    }

This code should be fairly easy to understand. Basically, the onclick calls the first javascript method, which then calls the controller. The controller builds the partial view and returns it. The first javascript method passes it to the second javascript method which sets the html of the div "top_video" to be the returned partial view.

If anything doesn't make sense, or anyone's having trouble with this in the future, let me know and I'll do my best to offer some help.

Sign up to request clarification or add additional context in comments.

1 Comment

Hi Eric, $('#top_video').html(response); It is not working for me.
1

I think there may be several confusing and inconsistent elements here.

First, you are returning a full view instead of a partial view. This reloads all containing elements, not just the part that is relevant to your partial view.

Second, you are using Url.Action, which only generates the url. I would recommend using Ajax.ActionLink, which allows you to do fully ajax calls, refreshing the content of your partial div and updating a target div element.

instead of:

<div class="videoList">
                <a href ="@Url.Action("Videos", "Home", new { topVideo = item.StatsVideoId })">
                    <img src="@Url.Content("~/Content/img/video-ph.png")" />
                </a>
                <p class="videoTitle">@item.Title</p>
            </div>

try the more modern solution

<div class="videoList">
@Ajax.ActionLink(
"Videos", 
"Home", 
"new { topVideo = item.StatsVideoId }, 
new AjaxOptions {  
    HttpMethod = "GET", 
    OnSuccess = "handleSuccess" 
}
)
</div>

This way you can be very specific on what you want each link to do, and you can pass along multiple parameters as well as define a callback function. You can also use "UpdateTargetId" in your ajax options to load your newly refreshed partial view into a DOM element.

6 Comments

I understand that. I know I need a new method in my controller that returns the partial view of the new video. What I don't know is how to call that through jquery and have the result overwrite what's currently in the 'top_videos' div.
I'm not sure I 100% understand your problem. Are you saying you need to know what the jquery equivalent of Ajax.ActionLink is? Or are you asking how to overwrite your 'top_videos' div with the result of your controller method?
Alright, I added an onclick to the link: onclick="updateTopVideo(@item.StatsVideoId)" Then I created a main.js file and included it in the view. The contents of this script file are: var updateTopVideo = function (itemId) { $.get('/Home/StatsVideo/' + itemId, "", callBack) }; var callBack = function (response) { $('#top_video').html(response) }; Finally, I added a new method to the controller called StatsVideo to return the partial view with a parameterof the selected video id. It seems like this should work, but I'm not hitting the breakpoint in my controller.
Hmm, it should. Are you seeing the request fire in fiddler? If so, did you decorate your controller with an HttpGet tag? That should instruct the routing to look for incoming get calls.
I changed the method in my controller from public ActionResult StatsVideo(int StatsVideoId) to public ActionResult StatsVideo(int Id) and it works now. I didn't know the parameter name had to be something specific to work!
|
1

You can remove the around the image and just store the url generated by the Url.Action in a data-href attribute.

Then you can use the jquery load method to load the data:

$(".videolist>img").click(function () {
    $("#content").load($(this).data("href"));
});

I created a fiddle that loads content dynamically here, so you can play with it if you want: http://jsfiddle.net/bTsLV/1/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.