Razor model helpers in jquery/handlebars infinite

2019-09-05 02:56发布

问题:

I'm using MVC5 and originally had a standard MVC implementation with manual paging and all was well. Except, when I showed it to my friend, he's like "What are all these number things down here?" (referring to the paging buttons, in his defense he was using his smart phone). It was then I decided infinite scroll would be much better.

After what seems like a million google searches, most the solutions (as well as ALL the solutions that I can actually understand) use json and jquery. Since I was using Troy Goode's PagedList already to do the manual paging, I went with his recommended solution here:

How Can I Convert My Paging Functionality To Use AJAX Insead?

And, I came up with this using json, jquery and handlebars:

<div id="incidentsList"></div>
<div id="incidentsWaypoint">.</div>

@section Scripts{
    <script id="incident-template" type="text/x-handlebars-template">
    <div class="tRoot">
        <div class="tRow">
            <div class="index-title">
                <a href="/Incidents/Details/{{IncidentId}}">{{Title}}</a>
            </div>
        </div>
        <div class="tRow">
            <div class="index-description">
                {{Description}}
            </div>
        </div>
        <div class="tRow">
            <div class="pCount">
                Count: {{Count}}
            </div>
            <div class="pSend">
                !!!!Partial View Here!!!!
            </div>
        </div>
    </div>
</script>
    <script type="text/javascript" src="/Scripts/handlebars-v3.0.3.js"></script>
    <script type="text/javascript" src="/Scripts/waypoints.min.js"></script>
    <script type="text/javascript">
    var source = $("#incident-template").html();
    var template = Handlebars.compile(source);
    $(function () {
        var page = 1;
        var $incdiv = $('#incidentsList');
        var $waypoint = $('#incidentsWaypoint');

        var opts = { offset: '100%' };
        $waypoint.waypoint(function () {
            $waypoint.waypoint('remove');
            $.getJSON('@Url.Action("AjaxPage", "Incidents")', { page: page++ }, function(incidents) {
                    $.each(incidents, function (index, incident) {
                        var pPartial = '@Html.Partial("_ProjectStatus", incident)';
                        //console.log(incident.Title);
                        //var context = { IncidentId: incident.IncidentId, Title: incident.Title, Description: incident.Description, Count: incident.Count };
                        var context = incident;
                        $incdiv.append(template(context));
                    });
                    $waypoint.waypoint(opts);
                });
            }, { offset: '100%' });
        });
    </script>
}

It works well as far as I can tell, except that I now seem to have lost the ability to use razor html helpers and such, more specifically that @Html.Partial("_ProjectStatus", incident) that has logic like:

if (!Model.IsOwner(Context.User.Identity.Name))
    {

        if (Model.IsSent(userId))
        {

So, I can't just generate straight html for that...

I was going to chop the handlebars template up into smaller templates and then hopefully use the razor helpers in jquery like I started with the var pPartial and then append it all together in the jquery code, but wanted to post it here first before I do all the work to see if I'm even on the right track, especially since (after many more searches) I haven't really found anyone trying to do this.

Therefore, my question(s) is (and I wouldn't expect them all answered, I'm just not sure what to ask and hoping someone can see what I'm trying to accomplish), will what I'm trying to do in the previous paragraph even work? Are razor helpers/logic out of the question in handlebars templates? Are there examples somewhere?...especially of someone who has a full implementation (i.e. something a little more complex than just a list where the example actually uses helpers/logic in it)? Is there another way to do infinite scroll that would allow me to keep my razor code or solely use partial views (or similar) with minimal jquery maybe?

As always, I appreciate any guidance. Thank you.

回答1:

So far, I fixed it by moving my view logic (learned from nerddinner...which also makes me think of another question) to the controller, by simply adding the last two lines to my json result and returning them as bools:

var incidents = listPaged.Select(items => new
        {
            items.IncidentId,
            items.Title,
            items.Description,
            items.Count,
            IsOwner = items.IsOwner(userName), // this one
            IsSent = items.IsSent(userId) //and this one
        });

Then in handlebars, I did:

{{#unless IsOwner}}
   {{#if IsSent}}
     <div class="sent">Sent...</div>
   {{else}}
     <div class="sent">Not Sent...</div>
   {{/if}}
{{/unless}}

I tried to do the partial view with @Html.Action and a few other things that were really straining my mind how they could even possibly work. I like to keep things simple and the couple things I got to sort-of work were noticeably slower (~20%).

This fix is slightly faster too by about 10% on average. Maybe because I'm not pulling every field in the model now? Anyway, wish I could use those helpers in the template, but i can live with this, especially since it allows me to move on...

I'd love to hear any other opinions. Thanks.