Adding multiple partial views and first one is missing form - javascript

I have the following:
_ImageGalleryPartial
#if (Model != null)
{
foreach (var item in Model)
{
#Html.Partial("_ImageItem", item);
}
}
_ImageItemPartial
#model WebsiteEngine.Models.PortfolioImage
#{
string url = VirtualPathUtility.ToAbsolute(String.Format("~/{0}", Html.DisplayFor(m => m.FileName)));
}
#using (Html.BeginForm("DeleteImage", "Portfolio", FormMethod.Post, new { #class = "deleteImageForm" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true);
#Html.HiddenFor(m => m.Name)
#Html.HiddenFor(m => m.FileName)
#Html.HiddenFor(m => m.Order)
#Html.HiddenFor(m => m.PortfolioID)
#Html.HiddenFor(m => m.PortfolioImageID)
<div class="span3">
<div class="item">
<a class="fancybox-button" data-rel="fancybox-button" title="Photo" href="#url">
<div class="zoom">
<img src="#url" alt="Photo" />
<div class="zoom-icon"></div>
</div>
</a>
<div class="details">
<i class="icon-remove"></i>
</div>
</div>
</div>
}
When I inspect the page elements using Chrome dev tools, the first element is missing the surrounding form. If I inspect the page source (using right) click then the form is there. This lead me to believe some JS was removing the form so I disabled JS but it was still missing.
If change _ImageGalleryPartial so it's like this (notice the addition of an empty model):
#if (Model != null)
{
#Html.Partial("_ImageItem", new WebsiteEngine.Models.PortfolioImage());
foreach (var item in Model)
{
#Html.Partial("_ImageItem", item);
}
}
Then all the "correct" elements get a form but again, this first item doesn't.
I'm still inclined to think this is a JS issue but I'm a little stumped as disabling JS doesn't fix it. Is this some off behaviour with MVC?
Just to note, I have simplified my layout above, I do actually have one or 2 nested forms but assume that's Ok as everything else is Ok, it's just this first partial that's broken.
Any ideas?

Html forms can't be nested.
Chrome will ignore illegal tags, thus they are not showing.
You can read this post for further information.

Related

Ajax functional on category selection

I am still very weak in Ajax, but they told me that this is a way out of the situation that I have developed.
I have a javascript function that filters categories. There is also alternation of lists in php.blade.
When I click on "All", all blogs are displayed and the alternation is working properly. When I select the "desired category", all blogs from this category are displayed, but alternation does not work.
I was prompted that you can is to call one ajax functional on category selection and return the HTML response on that ajax call. But I don't know how to do this, can anyone help?
JavaScript
$('.category-filter_item').click(function(){
$('.category-filter_item').removeClass('active')
$(this).addClass('active')
var dataFilter = $(this).attr('data-filter');
$('.blog-list').hide()
$(dataFilter).show()
})
php.blade
#extends('layouts.app')
#section('content')
<div class="container">
<div class="category-filter" id="filter">
<div class="category-filter_item active" data-filter="*">All</div>
#foreach($categories as $category)
<div class="category-filter_item" data-filter=".category_{{$category->id}}">{{ $category->title }}</div>
#endforeach
</div>
#foreach ($blogs as $index => $blog)
<div class="blog-list">
#if ($index % 2 === 1) //Alternation
<div class="blog blog--left" >
<h2 class="blog_title">{{ $blog->title }}</h2>
</div>
#else
<div class="blog blog--right">
<h2 class="blog_title">{{ $blog->title }}</h2>
</div>
#endif
</div>
#endforeach
</div>
#endsection
Controller
public function index()
{
$blogs = Blog::all();
$categories = Category:all();
return view('blog', compact('blogs', 'categories'));
}
Need to create new route and controller function to return only the selected category blogs and that should be in json format
Once that is done need to use the ajax call to the above route in the click function defined. Capture the response and then iterate and generate the html that should be inside the blog-list in your script. then update the html inside blog-list value.
refer this link
refer this for making ajax call link

How to submit a value by clicking on a div?

I'm working on Asp.net Mvc news website like (yahoo, BBC ...).
I have loads of divs that contains the feed title,text and image.What I want to achieve is to make these divs that contains these 3 elements clickable no matter where I clicked (title,text or feed image)and to post the value of the feed ID to my controller method.
I've done this already like this:
In my feed table I have : FeedID-FeedText-FeedPath
View:
#foreach (Feeds item in Model.FeedViewModel)
{
<div class="col-4">
#using (Html.BeginForm("goToFeed", "Home"))
{
<h3>#item.title</h3>>
<button type ="submit" name="FeedID" value="#item.FeedID"
style="background:none; border:none" href="#">#item.FeedText</button>
<img src="#Url.Content(#item.FeedPath)">
}
</div>
}
And in my controller I'm taking the "FeedID"
Controller:
[HttpPost]
public ActionResult goToFeed(int FeedID)
{
//some code here
}
I guess there should be a way to post the FeedID inside this div without making it a button.
I've checked these posts already but none of them helped me.
Form submit by click on a div element without JS
submiting form on div click with js
Thanks for any help...
You should not use a POST request to read data. The correct HTTP verb in this case would be GET. POST should mainly be used to create new entries. See Using HTTP Methods for RESTful Services.
This has not only academic reasons. If you use POST, and your users use the backwards/forwards buttons of the browser to navigate, they would see "Are you sure you want to resubmit the form?" messages.
To use GET, your CSHTML could look like this. Use CSS marker classes js-feed and js-feedId so you can later access these elements using jQuery.
#foreach (Feeds item in Model.FeedViewModel) {
<div class="col-4 js-feed">
<h3>#item.title</h3>>
<span>#item.FeedText</span>
#Html.HiddenFor(m => item.FeedID, new { #class = "js-feedId" })
</div>
}
The URL to the GET action is configured in the JS part. Extract the FeedId from the clicked div, replace the placeholder in the configured URL with this FeedId, and then redirect to this action by setting window.location.href, which will reload the page.
If you do not want to reload the entire page, use $.ajax instead.
<script type="text/javascript">
$(document).ready(function() {
var getUrl = '#Url.Action("goToFeed", "Home", new { FeedID = "To_Be_Replaced_By_JS" })';
$('.js-feed').on('click', function() {
var feedId = $('.js-feedId', $(this)).val(); // search only inside clicked element
var feedUrl = getUrl.replace('To_Be_Replaced_By_JS', feedId);
window.location.href = feedUrl;
});
});
</script>
The target controller action should be attributed with [HttpGet].
[HttpGet]
public ActionResult goToFeed(int FeedID) {
//some code here
}
Change this:
#foreach (Feeds item in Model.FeedViewModel)
{
<div class="col-4">
#using (Html.BeginForm("goToFeed", "Home"))
{
<h3>#item.title</h3>>
<button type ="submit" name="FeedID" value="#item.FeedID"
style="background:none; border:none" href="#">#item.FeedText</button>
<img src="#Url.Content(#item.FeedPath)">
}
</div>
}
To this:
#foreach (Feeds item in Model.FeedViewModel)
{
<div class="feed col-4">
#using (Html.BeginForm("goToFeed", "Home"))
{
#Html.HiddenFor(m => item.FeedID)
<h3>#item.title</h3>>
<button type ="submit" name="FeedID" value="#item.FeedID"
style="background:none; border:none" href="#">#item.FeedText</button>
<img src="#Url.Content(#item.FeedPath)">
}
</div>
}
Then add this to your page:
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script type="text/javascript">
$(function() {
$('.feed').click(function() {
return $(this).closest("form").submit();
});
});
</script>
Having a field is required when posting a razor form to the server so having the FieldID hidden will allow this to be sent. Having a div surrounding the area adding the onclick attribute with a submit function to post the above form document.forms[0].submit() can also be used.
#foreach (Feeds item in Model.FeedViewModel)
{
<div class="col-4">
#using (Html.BeginForm("goToFeed", "Home"))
{
<div onclick="this.parentNode.submit()">
#Html.HiddenFor(m => item.FeedID)
<h3>#item.title</h3>>
<button type ="submit" name="FeedID" value="#item.FeedID"
style="background:none; border:none" href="#">#item.FeedText</button>
<img src="#Url.Content(#item.FeedPath)">
</div>
}
</div>
}

make a link holding a model

I have a string Data in my model that can be pretty long. I'm trying to take the first 150 chars and then make it clickable, and when the link is clicked a new div should appear with the whole message. Below am I using tag, but I dont know how to give it a unique ID and make it store my item.Data.
Can someone help me with some ideas?
#foreach (var item in Model) {
<div class="row">
<div class="col-md-1">
#Html.DisplayFor(modelItem => item.Level)
</div>
<div class="col-md-2">
#Html.DisplayFor(modelItem => item.Source)
</div>
<div class="col-md-1">
#Html.DisplayFor(modelItem => item.Date)
</div>
<div class="col-md-5">
<a ID="?">#Html.DisplayFor(modelItem => item.Data).ToString().Substring(0, 150) ...</a>
</div>
<div class="col-md-1">
#Html.DisplayFor(modelItem => item.Count)
</div>
</div>
}
Essentially, you'll just need something like this:
<a class="show-data" href="#AllData">
#item.Data.Substring(0, 150)
</a>
<div id="#AllData" style="display:none">
#item.Data
</div>
Then, a bit of JS:
$('.show-data').on('click', function () {
$($(this).attr('href')).toggle();
});
Take note, though, for simplicity of the example, I just assigned the div an id of AllData. Since this is inside a foreach loop, you'll need to use something to make each id unique. This could be the id of the item or you could use a for loop instead of foreach, and then use the index. Just be sure to make the href of the link and the id of the div match and be unique for the page.
#Html.DisplayFor(modelItem => item.Data).ToString().Substring(0, 150)

Javascript not working in <a>

I'm having trouble with a new MVC4 site I'm working on. I can't seem to get the javascript to run at all. It doesn't throw an error, it just does nothing.
What am I missing?
Here's my page code:
#model IEnumerable<WiseGalleriesEntities.Medium>
#{
ViewBag.Title = "ManageMedium";
}
<div class="title">
<h1>Mediums...</h1>
</div>
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#using (Ajax.BeginForm("Create", "Medium", new AjaxOptions() { UpdateTargetId = "MediumListDiv" }, new { id = "frmAddMedium" }))
{
<div class="span12">
<div>
<div class="editor-field">
#Html.TextBox("txtDescription")
</div>
</div>
Add Medium
</div>
}
<div id="MediumListDiv">
#Html.Partial("Medium.List", Model)
</div>
Instead of using the href attribute, use the onclick attribute.
<a onclick="$('#frmAddMedium').submit();" class="btn-primary btn-small">Add Medium</a>

Ajax.ActionLink created from Ajax.BeginForm in a RenderPartial View

I would like to confirm if this limitation is by design or if I'm doing something wrong:
I have a View with two RenderPartials:
#model Heelp.ViewModels.CompanyIndexViewModel
#{ Html.RenderPartial(MVC.Company.Views.IndexSearch, Model.SearchViewModel); }
#{ Html.RenderPartial(MVC.Company.Views.IndexMap, Model.MapViewModel); }
In the first Partial View I have an Ajax.BeginForm:
#model Heelp.ViewModels.CompanyIndexSearchViewModel
#using (Ajax.BeginForm(MVC.Company.CategoryGetAllBySearch(), new AjaxOptions { UpdateTargetId = "searchCompanyResults", InsertionMode = InsertionMode.Replace }, new { #id = "searchBoxWrap" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.IsCenterFromUser)
#Html.HiddenFor(m => m.CenterLat)
#Html.HiddenFor(m => m.CenterLng)
#Html.HiddenFor(m => m.Zoom)
#Html.HiddenFor(m => m.SearchRadius)
#Html.TextBoxFor(m => m.Search, new { #placeholder = #HeelpResources.CompanyIndexViewSearchPlaceholder })
<input type="button" value="«" id="clearKeywords"/>
#Html.TextBoxFor(m => m.Location, new { #placeholder = #HeelpResources.CompanyIndexViewLocationPlaceholder })
<input type="button" value="«" id="clearLocation"/>
<input type="button" value="X" id="hereButton"/>
<input type="submit" value="#HeelpResources.CompanyIndexViewSearchButtonLabel"/>
}
<div id="searchCompanyResults" class="clearfix" style="z-index: 10; position: absolute; width: 400px;"></div>
The Ajax.BeginForm generates a PartialView in the searchCompanyResults div with a list of Ajax.ActionLink's:
#model Heelp.ViewModels.CategoryGetAllBySearchListViewModel
<p class="float-left margin-top align-left"><span>Encontrámos <em>#Model.TotalSearchCount</em> resultados nas categorias:</span></p>
<div class="clear-both">
<div id="searchResultsList" class="float-left">
<ul>
#foreach (var item in Model.CategoryGetAllBySearch)
{
<li>
#Ajax.ActionLink(
String.Format("{0} {1} ver »", item.SearchCount, item.Name),
MVC.Company.GetAllByCategory(item.Id, Model.Search, Model.Location, Model.IsCenterFromUser, Model.CenterLat, Model.CenterLng, Model.SearchRadius),
new AjaxOptions { OnBegin = "CompanyGetAllByCategoryOnBegin(" + item.Id + ")", OnSuccess = "CompanyGetAllByCategoryOnSuccess" })
</li>
}
</ul>
</div>
</div>
The problem here is that, if I don't include a link to "< script src="~/Scripts/jquery.unobtrusive-ajax.min.js" >" in the PartialView the Action.Link returns the Json text.
EDIT: One I detected is that when I click the Action.Link, the submit is made 2 times the first time, and 4 the second, and on and on growing, why?
Do I have to do this?
If you want use Ajax.BeginForm, Ajax.ActionLink and others from Ajax you should include jquery.unobtrusive-ajax.js file in your layout. It contains code that intercept click on link and submit of the form by cancel action and make it over AJAX.
You don't need include that file in partial views twice.

Categories

Resources