I have a mvc 5 project using a database.
In my project I have a Blog-page. This page is loaded using a controller.
In the page I dynamically create a list of items (blogitems) using a simple '#foreach(var item in collection).
Each item has an id (off course), a title and a description.
#foreach (var item in Model.VmBlogItems)
{
<div class="allblogs">
<div class="blogtitle">
<h4>#item.Title</h4>
</div>
<div id="allblogcontent">
#item.Description
</div>
<a id="moreless" href="">Lees meer</a>
</div>
}
My question now is how I can create a button so that when clicked on it the description is hidden or shown.
I also wrote some jquery:
<script type="text/javascript">
//when ready
$(function () {
$('#allblogcontent').hide();
$('#moreless').click(function () {
$('#allblogcontent').toggle();
});
});
</script>
However when I try this, all my items show or hide the Description.
Does anybody know how I make sure that only the Description of the selected item is shown or hidden? I just spend 6 hours reading, trying and sadly enough failing to make it work. I could use some help.
First you modify the markup so each description tag has a unique id attached to it, and the corresponding button has a reference to that id
#{
int i=0;
}
#foreach (var item in Model.VmBlogItems)
{
i++;
<div class="allblogs">
<div class="blogtitle">
<h4>#item.Title</h4>
</div>
<div id="allblogcontent#i" class='someclass'>
#item.Description
</div>
<a id="moreless" href="" data-desc-id='allblogcontent#i'>Lees meer</a>
</div>
}
Your code can figure out which is which now.
<script type="text/javascript">
//when ready
$(function () {
$('.someclass').hide();
$('#moreless').click(function () {
$('#' + $(this).attr('data-desc-id')).toggle();
});
});
</script>
A footnote
This approach will make static references between the tags, so you can move the markup around if you like. The other two solutions shown here, so far, will break if you change the order of the tags.
Just change the below section from
$('#moreless').click(function () {
$('#allblogcontent').toggle();
});
to
$('#moreless').click(function () {
$(this).siblings('#allblogcontent').toggle();
});
Related
<div class="container">
#section HeroSection{
#foreach (var category in Model.AllCategory.Where(m => m.IsFeatured).FirstOrDefault().CategoryPictures.Select(m => m.Picture).Distinct())
{
<div class="hero__item set-bg" data-setbg="/FileStore/images/#category.Url">
<div class="hero__text">
<span>FRUIT FRESH</span>
<h2>Vegetable <br />100% Organic</h2>
<p>Free Pickup and Delivery Available</p>
SHOP NOW
</div>
</div>
}
}
</div>
</div>
</div>
}
</div>
I tried to #Render the //#section HeroSection// as false in _layout page .so that it will only appear in home/index ..not in other pages!
I can think of 2 approaches.
the first one is not so practical which is making 2 different layouts, one without the div and one with it. And you can change the layout of the homepage in the razor file like this
#{Layout = "YourNewLayOut"}
The other approach which I think it's better is to use JavaScript.
you can use window.location.href to get the current url and check if it's the url of the home page you target the div and make hidden otherwise visible.
your function should look like this :
function someFunctionName() {
let div = document.querySelector("#yourDiv");
if (window.location.href === "your home page url ") {
div.style.display = "none";
} else {
div.style.display = "block or flex or what ever you're using";
}
}
and then Invoke this function on loading like this
window.onload = function() {
someFunctionName();
};
this is my .cshtml page code,i use jquery repeater is in this code repeater is working fine but i want to add some modification in this repeater but i am stuck here. you can see my code.
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data", #class = "repeater" }))
{
<div data-repeater-list="">
<div data-repeater-item="">
<div class="col-lg-12 col-md-12 col-sm-12">
<input type="file" name="Docfiles" />
</div>
</div>
</div>
<input data-repeater-create type="button" value="Add" />
<button>Save</button>
}
#section Scripts{
<!-- Import repeater js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.repeater/1.2.1/jquery.repeater.js"></script>
<script>
$(document).ready(function () {
$('.repeater').repeater({
// (Optional)
// start with an empty list of repeaters. Set your first (and only)
// "data-repeater-item" with style="display:none;" and pass the
// following configuration flag
initEmpty: true,
// (Optional)
// "show" is called just after an item is added. The item is hidden
// at this point. If a show callback is not given the item will
// have $(this).show() called on it.
show: function () {
$(this).slideDown();
},
// (Optional)
// "hide" is called when a user clicks on a data-repeater-delete
// element. The item is still visible. "hide" is passed a function
// as its first argument which will properly remove the item.
// "hide" allows for a confirmation step, to send a delete request
// to the server, etc. If a hide callback is not given the item
// will be deleted.
hide: function (deleteElement) {
if (confirm('Are you sure you want to delete this element?')) {
$(this).slideUp(deleteElement);
}
},
// (Optional)
// Removes the delete button from the first list item,
// defaults to false.
isFirstItemUndeletable: true
})
});
</script>
}
i want to change html in this formate like this as shown in below screenshot.
Firstly,the name format is set in jquery.repeater.js,if you want to change it,you need to change jquery.repeater.js,here is a demo worked:
1.Add the jquery.repeater.js to your project.
I copy the js to my project like this:
2.Find setIndexes in the jquery and change var newName = groupName + '[' + index + '][' + name + ']' +like this(You can also change it to other format you want):
3.change your script src from cdnjs to your own project:
<script src="~/lib/jquery-repeater/jquery.repeater.js"></script>
4.Result:
I have a c# application using a repeater and jQuery to add a little pizzaz to my application. The first portion of the jQuery functions correctly as the content slides up and down to hide or show whatever ONE section had been clicked on, but the second portion changes all classes including the one inside the section clicked. Why is this?
Here is my repeater layout:
<ItemTemplate>
<div class="head"><span class="expand"> </span> <%#Eval("Job_Title") %></div>
<div class="row" style="margin:0px 0px 20px 50px; display: none;">
<div><%#Eval("Status") %></div>
<div><%#Eval("Department") %></div>
<div><%#Eval("Posting_Site") %></div>
<div><%#Eval("Job_Duties") %></div>
</div>
</ItemTemplate>
Here is my jQuery:
<script type="text/javascript">
$(function () {
$('.head').click(function () {
$(this).next('div.row').stop(true, true).slideToggle(400, function () {
$('.expand').toggleClass('collapse');
});
});
});
</script>
$('.expand') targets all elements with that class, if you just want to target the one inside the current .head you'd do
$(this).prev('.head').find('.expand').toggleClass('collapse')
or the opposite would be
var thisOne = $(this).prev('.head').find('.expand');
$('.expand').not(thisOne).toggleClass('collapse');
Your use of a class as your selector and then using next, means that you are iterating over each 'head' that contains 'div.row'.
You need to change it this:
$(function () {
$('.head').click(function () {
$('.head div.row').slideToggle(400, function () {
$('.expand').toggleClass('collapse');
});
});
});
I'm trying to implement the select2 on my master layout of my ASP.NET MVC 4 website.
I want it to, as soon as the user starts typing (minimum of 2 letters), call my method to query the database using the letters the user has already typed. Except, when I start typing, my method never gets called. I threw in some alerts and I'm able to see what I'm typing, but the select2 isn't firing, I think.
Here's the script and css references in the tag:
<script src="/Content/select2/select2.js"></script>
<link href="/Content/select2/select2.css" rel="stylesheet" />
Here's the search box in my layout.cshtml file:
<div class="navbar-header hidden-xs pull-right" style="padding-top: 10px; margin-left: 10px;">
<input id="search" class="form-control" placeholder="Search..." type="text" data-autocomplete-url="/Home/AutoFillValues" />
</div>
And here's the bottom of my layout page where the select2 stuff appears:
<script src="/Scripts/jquery-1.9.1.min.js"></script>
<script src="/Scripts/bootstrap.min.js"></script>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryui")
#Scripts.Render("~/bundles/jqueryval")
#RenderSection("scripts", required: false)
<script type="text/javascript">
$(document).ready(function () {
$("#search").select2({
placeholder: "Search...",
minimumInputLength: 2,
ajax: {
url: "~/Home/AutoFillSearch",
dataType: 'jsonp',
data: function(search) {
return {
q: search
};
},
results: function(search, page) {
return { results: data.Results };
}
}
});
});
</script>
Lastly, here's my controller method (I'm not worried about the code here yet, I just want to see my breakpoint get hit at the first line...):
public ActionResult AutoFillValues()
{
// Get all wrestlers and all teams
var players = _playerRepo.Query().Where(w => w.Division == "Division I" && w.Conference != null);
var schools = players.Select(w => w.School).Distinct();
ArrayList list = new ArrayList();
foreach (var school in schools)
{
var hyperlinkFormat = "{1}";
//#HttpUtility.UrlEncode(Model.Team.Name, System.Text.Encoding.UTF8)
list.Add(string.Format(hyperlinkFormat, string.Format(RosterPath, school), string.Format(RosterText, school)));
}
foreach (var player in playerss)
{
var hyperlinkFormat = "{1}";
//#HttpUtility.UrlEncode(Model.Team.Name, System.Text.Encoding.UTF8)
list.Add(string.Format(hyperlinkFormat, string.Format(RosterPath, player.School), string.Format(RosterText, player.School)));
}
return Json(list.ToArray());
}
I had to upgrade to jQuery 2.1 (because of the issue with version 1.9 and the .live/.on functions) in order for my select2 to start firing.
Now I just need to get my select2 styled...
I would like some advice on this matter. I have a view page that will display a number of users. One view is to display users in a grid (gallery like) of their images. Second view is to display the same users but by their name in a list layout. I will have a toggle button on the page to switch between the two. What is the best way to go about it? Having two separate view pages or have a partial view of some sort?
Update Code after suggestion below
<div data-bind="template: {name:'grid-template'}"></div>
<div data-bind="template: {name:'list-template'}"></div>
<script style="float:left" type="text/html" id ="grid-template">
<section " style="width:100%; float:left">
<section id="users" data-bind="foreach: Users">
<div id="nameImage">
<figure id="content">
<img width="158" height="158" alt="Gravatar" data-bind="attr:{src: GravatarUrl}"/>
<figcaption>
<a title="Email" id="emailIcon" class="icon-envelope icon-white" data-bind="attr:{'href':'mailto:' + Email()}"></a>
<a title="Profile" id="profileIcon" class="icon-user icon-white"></a>
</figcaption>
</figure>
<p data-bind="text:Name"></p>
</div>
</section>
</section>
</script>
<script style="float:left" type="text/html" id="list-template">
<div data-bind="foreach: Users">
<div style="width:60%; float:left; margin:10px; height:58px">
<img style="float:left; margin-right:5px" width="58" height="58" alt="Gravatar" data-bind="attr:{src: GravatarUrl}"/>
<p style="height:58px; float:left; vertical-align:central" data-bind="text:Name"></p>
<a style="float:right" title="Profile" class="icon-user icon-black"></a>
<a style="float:right" title="Email" class="icon-envelope icon-black" data-bind="attr:{'href':'mailto:' + Email()}"></a>
</div>
</div>
</script>
Knockout Script File
$.views.User.UserViewModel = function (data) {
var self = this;
self.Name = ko.observable(data.Name);
self.Email = ko.observable(data.Email);
self.ContentRole = ko.observable(data.ContentRole);
self.MD5Email = ko.observable(data.MD5Email);
self.GravatarUrl = ko.computed(function () {
return 'http://www.gravatar.com/avatar/' + self.MD5Email() + '?s=300&d=identicon&r=G';
});
self.renderMode = ko.observable('grid');
self.displayTemplate = ko.computed(function () {
return self.renderMode() + '-layout-template';
});
};
Personally, I like having clean isolated small little Partial Views especially if it is going to be regular HTTP POST.
However, based on the assumptions I am making below, I think I can suggest a better implementation design.
My Assumption
You have
Index.cshtml Parent view to display a list Users.
JSON object array containing your list of Users
Based on what I see, you are using KnockoutJS.
Read the KnockoutJS Template Binding especially the "Note 5: Dynamically choosing which template is used" part.
It kind of makes it easier to do what you are doing if you are using KnockoutJS or something similar.
You simply have toggle between the two rendering templates.
<script type="text/html" id="gallery-layout-template"> ... </script>
<script type="text/html" id="listing-layout-template"> ... </script>
<div id="divOutputContainer"
data-bind="template: { name: displayTemplate, foreach: users }"></div>
<script type="text/javascript">
$(document).ready(function() {
// I am just writing out a dummy User array here.
// Render out your User Array JSON encoded using JSON.NET.
var myUsers = [
{ "id" : 1, "name": "User 1" },
{ "id" : 2, "name": "User 2" }
];
// here is your KnockoutJS View Model "class"
function MyKoViewModel(users) {
var self = this;
self.users = ko.observableArray(users);
// Toggle this renderMode observable's value
// between 'listing' and 'gallery' via your Toggle button click event handler
self.renderMode = ko.observable( 'gallery' );
self.displayTemplate = function(user) {
// this will return 'gallery-layout-template' or 'listing-layout-template'
return self.renderMode() + '-layout-template';
}
}
ko.applyBindings( new MyKoViewModel( myUsers ) );
});
</script>
So with that technique, you don't need to make an AJAX call every time to refresh the view with a different rendering template.
You have all your data that you want to display as a client-side JavaScript KnockoutJS view model.
Then, just switch the client-side rendering template using KnockoutJS.
Must more efficient :-)
NOTE
I have a feeling, you might have to use the ko.computed() for the MyKoViewModel's displayTemplate() function like this.
self.displayTemplate = ko.computed(function() {
return self.renderMode() + '-layout-template';
}