I am using the MVC Widget Template to read a list of Dynamic Content, but need to be able to query the list. Because it has pagination, it only goes through the first 20 or so. How do I turn this off?
I Tried using this but didnt work:
<telerik:RadListView ID="KBList" ItemPlaceholderID="ItemsContainer" runat="server"
EnableEmbeddedSkins="False" EnableEmbeddedBaseStylesheet="False"
AllowPaging="False">
My Code Here:
#model Telerik.Sitefinity.Frontend.DynamicContent.Mvc.Models.DynamicContentListViewModel
#using Telerik.Sitefinity.Frontend.DynamicContent.WidgetTemplates.Fields.Helpers;
#using Telerik.Sitefinity;
#using Telerik.Sitefinity.Data.ContentLinks;
#using Telerik.Sitefinity.Frontend.Mvc.Helpers;
#using Telerik.Sitefinity.Frontend.Mvc.Models;
#using Telerik.Sitefinity.Web.DataResolving;
#using Telerik.Sitefinity.Model.ContentLinks;
#using Telerik.Sitefinity.Modules.Pages;
#Html.Script(ScriptRef.JQuery, "top", false)
<div class="#Model.CssClass">
<ul>
#foreach (var item in Model.Items)
{
var navigateUrl = HyperLinkHelpers.GetDetailPageUrl(item, ViewBag.DetailsPageId, ViewBag.OpenInSamePage, Model.UrlKeyPrefix);
<li #Html.InlineEditingAttributes(Model.ProviderName, Model.ContentType.FullName, (Guid)item.Fields.Id)>
<h3>
<a #Html.InlineEditingFieldAttributes("Title", "ShortText") href="#navigateUrl">
#item.Fields.Title
</a>
</h3>
</li>
}
</ul>
#if (Model.ShowPager)
{
#Html.Action("Index", "ContentPager", new { currentPage = Model.CurrentPage,
totalPagesCount = Model.TotalPagesCount.Value,
redirectUrlTemplate = ViewBag.RedirectPageUrlTemplate })
}
</div>
You need to edit the widget in page edit mode and there find the List Settings tab and once there you select the No Limit and Paging option.
This way, all items will be sent to the view.
Try writing your own MVC widget. In the Index method of your controller try fetching all content using resolveType of the dynamic module and (if needed convertinto required model) and pass it to your view file.
public ActionResult Index()
{
DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(String.Empty,"SomeName");
Type dynArticleType = TypeResolutionService.ResolveType(resolveType);
var FilteredCollection = dynamicModuleManager.GetDataItems(dynArticleType)
.Where(x => x.Status == ContentLifecycleStatus.Live && x.Status != ContentLifecycleStatus.Deleted
&& x.Status != ContentLifecycleStatus.Temp && x.Status != ContentLifecycleStatus.Master)
.OrderByDescending(x => x.GetValue<System.DateTime>("PublicationDate"));
var fullList = FilteredCollection.ToList();
//Convert into customModel.
return View("Default", yourCustomModel);
}
Related
I'm using cloudscribe navigation to build the sidebar and associated breadcrumb menu
I couldn't find it in the help documentation, so posting here
we have some route parameters in our routing templates - I'm unsure how to preserve those in breadcrumbs, navigation parameter preservedRouterParameters I understand that only works with Query string params
our route is something like this:
{wholesaleCustomerCode}/{area:exists}/{baseItemId:guid}/{controller=Home}/{action=Index}/{id:guid?}
and would translate to something like :
http://127.0.0.1:5100/TOM/Service/09185d87-5e3f-4217-a0b9-02f766efc714/Home/Detail
now when I'm on the /Detail view - it's nested quite deep - but the previous parent in breadcrumb loses baseItemId value - any suggestions how I can preserve route parameters in the breadcrumb hierarchy ?
I have attempted the following, just to test if it would pick up preserve route parameters, but didn't work
<Children>
<NavNode
key="d902daaa-99ec-488a-85de-c03641fb547d"
area="Service"
controller="Home"
action="Detail"
text="Service"
iconCssClass=""
componentVisibility="breadcrumbs"
viewRoles="Administrator"
preservedRouteParameters="baseItemId"
>
<Children>
<NavNode
key="3047c57d-0f8c-4875-aff9-9c1f91909e41"
area="Service"
controller="RecurringCredit"
action="Edit"
text="Recurring Credit"
iconCssClass=""
componentVisibility="breadcrumbs"
viewRoles="Administrator"
preservedRouteParameters="baseItemId"
>
</NavNode></Children></NavNode>
It is true that preservedRouteParameters only works for query string parameters.
One possible solution is to use code from within the controller action for your detail view to update the url for the parent breadcrumbs as needed. Relevant documentation here:https://www.cloudscribe.com/docs/adjusting-menu-items-per-request
var crumbAdjuster = new NavigationNodeAdjuster(Request.HttpContext);
crumbAdjuster.KeyToAdjust = "d902daaa-99ec-488a-85de-c03641fb547d";
crumbAdjuster.AdjustedUrl = // set the url here as you want it to be;
crumbAdjuster.AddToContext();
that will update the url for the given menu node for the life of the current request
Here's how I solved the issue
Consider you have the following default BootstrapBreadcrumbs view from cloudscribe.Web.Navigation/Views:
#using cloudscribe.Web.Navigation
#model NavigationViewModel
#if (Model.CurrentNode != null && (Model.ParentChain.Count > 1 || (Model.TailCrumbs != null && Model.TailCrumbs.Count > 0)))
{
<ul class="breadcrumb">
#foreach (var node in Model.ParentChain)
{
if (!Model.ShouldAllowView(node)) { continue; }
if (node.EqualsNode(Model.CurrentNode))
{
if (Model.TailCrumbs != null)
{
<li>#Model.AdjustText(node)<span class="divider"></span></li>
}
else
{
<li class="active">#Model.AdjustText(node)</li>
}
}
else
{
<li>#Model.AdjustText(node)<span class="divider"></span></li>
}
}
#if (Model.TailCrumbs != null)
{
foreach (var n in Model.TailCrumbs)
{
<li class="active">#n.Text</li>
}
}
</ul>
}
instead of using Model.AdjustUrl bypass it in favour of using asp-route-* helper
#using cloudscribe.Web.Navigation
#model NavigationViewModel
#{
var id = ViewContext.RouteData.Values["id"];
var baseItemId = ViewContext.RouteData.Values["baseItemId"];
var orderId = ViewContext.HttpContext.Request.Query["orderId"];
}
#if (Model.CurrentNode != null && (Model.ParentChain.Count > 1 || (Model.TailCrumbs != null && Model.TailCrumbs.Count > 0)))
{
<ul class="breadcrumb">
#foreach (var node in Model.ParentChain)
{
if (!Model.ShouldAllowView(node)) { continue; }
if (node.EqualsNode(Model.CurrentNode))
{
if (Model.TailCrumbs != null)
{
<li><a asp-area="#node.Value.Area" asp-controller="#node.Value.Controller" asp-action="#node.Value.Action" asp-route-baseItemId="#baseItemId" asp-route-orderId="#orderId" asp-route-id="#id">
#Model.AdjustText(node)
</a>
<span class="divider"></span>
</li>
}
else
{
<li class="active">#Model.AdjustText(node)</li>
}
}
else
{
<li><a asp-area="#node.Value.Area" asp-controller="#node.Value.Controller" asp-action="#node.Value.Action" asp-route-baseItemId="#baseItemId" asp-route-orderId="#orderId" asp-route-id="#id">#Model.AdjustText(node)</a><span class="divider"></span></li>
}
}
#if (Model.TailCrumbs != null)
{
foreach (var n in Model.TailCrumbs)
{
<li class="active">#n.Text</li>
}
}
</ul>
}
this implementation has some drawbacks and may not work for everyone - for example, all the previous breadcrumbs hierarchy now have baseItemId in the route -
e.g.
dashboard / all notes / note / detail
here , the all notes will also have the baseItemId added to it, although it doesn't need it -
but it works for us as it's an administrative portal (no SEO requirements) and the way our route templates are mapped
Might be a asked and answered...sorry but, I've been searching for a while.
RAZOR VIEW
#foreach (var item in Model.LanguageList)
{
<li>
<a href="#Url.Action("ChangeLanguage", "UserHeader")" data_languageID="#item.LanguageID" data_someval="hello" data_somevalb="world">
<div class="flag #item.LanguageFlag">
</div>
<div class="flag-title"> #item.LanguageName</div>
</a>
</li>
}
How do I access the data attributes in my controller?
CONTROLLER
public ActionResult ChangeLanguage()
{
var x = ControllerContext; //// ??? get the collection of [data-xx] from where?
return RedirectToAction("Buttons", "Designer");
}
data-* attributes are client side values and are not sent in the request.
In order to send those values, add them as route values
#foreach (var item in Model.LanguageList)
{
<li>
<a href="#Url.Action("ChangeLanguage", "UserHeader", new { languageID=item.LanguageID, someval="hello", somevalb="world" })">
<div class="flag #item.LanguageFlag"></div>
<div class="flag-title"> #item.LanguageName</div>
</a>
</li>
}
and include parameters in your GET method for the values
public ActionResult ChangeLanguage(int LanguageID, string someval, string somevalb)
Alternatively you could handle this using javascript/jquery (the ChangeLanguage() method also needs to be modified as shown above)
$('a').click(function() {
// get the url
var url = $(this).attr('href');
// get the data attributes
var languageID = $(this).data('languageID');
var someVal= $(this).data('someval');
var someValB= $(this).data('somevalb');
location.href = url + '?languageID=' + languageID + '&someVal =' + someVal + '&someValB=' + someValB;
return false; // cancel the default redirect
});
So, I am sending a dictionary object to my view from the controller.
// GET: QuestionResponses/Create
public ActionResult Create(int questionnaireUID)
{
var questions = from q in db.QUESTIONS
where q.QuestionnaireUID == questionnaireUID
select q;
ViewBag.NextQuestion = from q in db.QUESTIONS
where q.QuestionnaireUID == questionnaireUID
select new SelectListItem
{
Selected = (q.QuestionnaireUID == questionnaireUID),
Text = q.Question1,
Value = q.QuestionUID.ToString()
};
Dictionary<QUESTION, QUESTION_RESPONSES> dict = new Dictionary<QUESTION, QUESTION_RESPONSES>();
foreach (var question in questions)
{
dict.Add(question, new QUESTION_RESPONSES { QuestionUID = question.QuestionUID, Response = "", NextQuestion = "" });
}
return View(dict);
}
The reasoning behind this is that I need to view data from one model and need to add/edit data from another model. I tried using Tuples and was not able to get it to work (if you could tell me how to do this with Tuples, that would be helpful too).
This is what the view does with this Dictionary object.
<div class="form-group">
<h2> Reponses </h2>
<p> For each question, enter in the appropriate response(s). All questions must have at least one response. <p>
<div id="editorRows">
<div class="rows_no_scroll">
#foreach (var item in Model.ToArray())
{
<!-- The question that responses are being added to. -->
Html.RenderPartial("QuestionRow", item.Key);
<!-- All questions pertaining to this questionnaire. -->
// <p>Please select the question which should be asked as a response to this question.</p>
#Html.DropDownList("NextQuestion", null, htmlAttributes: new { #class = "form-control", id = "ddl_questions_" + count})
#Html.ValidationMessageFor(model => item.Value.NextQuestion, "", new { #class = "text-danger" })
<!-- The next question link and responses being inputted by user. -->
Html.RenderPartial("ResponseEditorRow", item.Value);
// <p> Question #count </p>
count += 1;
}
</div> <!--/rows_no_scroll-->
</div> <!-- /editorRows -->
</div> <!-- /form-group -->
For completeness, here are what the partial views are doing.
QuestionRow:
<div class="questionRow">
<!-- Hide attribute(s) not being viewed/edited. -->
#Html.HiddenFor(model => model.QuestionUID)
#Html.HiddenFor(model => model.QuestionnaireUID)
<!-- Show attribute(s) being viewed. -->
#Html.DisplayFor(model => model.Question1)
<div class="addQuestion">Add Response</div>
</div>
ResponseEditorRow:
<div class="editorRow">
#using (Html.BeginCollectionItem("questions"))
{
<!-- Hide attribute(s) not being viewed/edited. -->
#Html.HiddenFor(model => model.ResponseUID)
#Html.HiddenFor(model => model.QuestionUID)
<br>
<!-- Display attribute(s) being edited. -->
#Html.EditorFor(model => model.Response, new { htmlAttributes = new { #type = "text", #name = "question", #class = "question_input" } })
#Html.ValidationMessageFor(model => model.Response, "", new { #class = "text-danger" })
<input type="button" name="addRow[]" class="deleteRow" value="Delete">
}
</div>
The problem that I am having is that when I get back to my controller to POST the data inserted by the user, my Dictionary is empty. I'm not sure if I am inserting the information correctly. I am changing the dictionary object toArray(), not sure if this is affecting anything...
Here is the HTTP POST create method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ResponseUID, QuestionUID, Response, NextQuestion")] Dictionary<QUESTION, QUESTION_RESPONSES> question_question_response)
{
if (ModelState.IsValid)
{
foreach (var item in question_question_response.ToArray())
{
db.QUESTION_RESPONSES.Add(item.Value);
db.SaveChanges();
return RedirectToAction("Index"); // Update to take user to Actions/Create page.
}
}
ViewBag.NextQuestion = new SelectList(db.QUESTIONS, "QuestionUID", "Question1");
return View(question_question_response);
}
Open to any suggestions of different ways I could do this or on what may be wrong with what I am currently doing.
Create 2 ViewModels:
public class QuestionAireViewModel {
public int QuestionAireId {get;set;}
public List<QuestionViewModel> Quesitons {get;set;}
}
public class QuestionViewModel{
public int QuestionId {get;set;}
public string Question {get;set;}
public string QuestionResponse {get;set;}
}
In your view pass this QuestionAireViewModel
Generate QuestionAireViewModel in your controller like this:
public ActionResult GetQuestions(int id)
{
var questionAire = db.QuesitonAire.First(s => s.QuestionAireId == id)
var questions = new List<QuestionViewModel>();
foreach(var question in questionAire.Questions){
questions.Add(new QuestionViewModel(){
Quesiton = question.Question,
});
}
var model = new QuestionAireViewModel(){
QuestionAireId = questionAire.Id,
Quesitons = questions
};
return View(model);
}
Then on POST Form method will be:
[HttpPost]
public ActionResult SaveQuestions(QuestionAireViewModel model)
{
}
I have been using ASP.NET MVC 4 for a while but I have not yet come across a situation where i need to insert a value into the database from a scaffolded Create view which is based on a value passed from another view. I have tried to infer from the Edit view to try and modify my code to work but I have run into a snag. I got an error similar to this post. Here is my code from the view passing the value
#Html.ActionLink("Allocate", "Create", "Allocation", new { id=item.requestID}, null)
this is from the list of requests already in the database from the Index view
here is my code on the controller that is trying to force the Create method to use the ID passed from the link above
public ActionResult Create(int id = 0)
{
Request request = db.Requests.Find(id);
ViewBag.requestID = new SelectList(db.Requests, "requestID", "requestID", request.requestID);
return View(request);
}
then here is the posting code to the db
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Allocation allocation)
{
if (ModelState.IsValid)
{
db.Allocations.Add(allocation);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.requestID = new SelectList(db.Requests, "requestID", "requestID", allocation.requestID);
return View(allocation);
}
Basically what I am trying to do is allocate funds to a request made where by the allocation is entered into the db based on the request id. I am trying to prevent the user from choosing the request id from a drop down list. When I run this i get an error
The model item passed into the dictionary is of type 'System.Data.Entity.DynamicProxies.Request_A52006F7570E0448EE323CB36858E4D13EED0BAD958340B32FF166708545DA8C', but this dictionary requires a model item of type 'BudgetAllocation.Models.Allocation'.
If theres anyone out there who can help me out with this please do as soon as you can. I appreciate all the effort offred!!!!!
//EDIT
Here is my Create view
#model BudgetAllocation.Models.Allocation
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Allocation</legend>
#Html.HiddenFor(model => model.requestID)
<div class="editor-label">
#Html.LabelFor(model => model.allocAmount, "Amount")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.allocAmount)
#Html.ValidationMessageFor(model => model.allocAmount)
</div>
<p>
<input type="submit" value="Allocate" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
The problem is your view id strongly typed with BudgetAllocation.Models.Allocation while in get action of Create you are passing object of type BudgetAllocation.Models.Request thats why you are getting the exception.
You have to pass object of type BudgetAllocation.Models.Allocation in Create get action as well because you view is strongly typed to it.
public ActionResult Create(int id = 0)
{
Request request = db.Requests.Find(id);
return View(request) // <-------------- here is the mistake
}
it should return allocation object, something like this, it is just an example may be you need to do some other thing instead of selecting:
public ActionResult Create(int id = 0)
{
Allocation allocation = db.Allocations.Find(x=>x.requestID == id);
ViewBag.requestID = new SelectList(db.Requests, "requestID", "requestID", request.requestID);
return View(allocation);
}
UPDATE:
you simply need to do like this not return allocaiton object return simply View:
public ActionResult Create(int id = 0)
{
ViewBag.requestID = new SelectList(db.Requests, "requestID", "requestID", request.requestID);
return View();
}
I am trying to create a cascading drop down list, and I am getting an error.
This contains what I am try to do with in my controller class:
public ActionResult Create()
{
ViewBag.Status = new SelectList(db.pjt_Statuses, "pjt_Status_ID", "StatusName");
ViewBag.CategoryID = new SelectList(db.pjt_Categories, "pjt_Category_ID", "CatName");
return View();
}
public ActionResult SubCategory(int id)
{
var SubCategory = from s in db.pjt_SubCategories
where s.CategoryID == id
select s;
return Json(SubCategory.ToList());
}
// POST: /Project/Create
[HttpPost]
public ActionResult Create(pjt_Projects pjt_projects)
{
if (ModelState.IsValid)
{
pjt_projects.CreationDate = DateTime.Now;
db.pjt_Projects.Add(pjt_projects);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.Status = new SelectList(db.pjt_Statuses, "pjt_Status_ID", "StatusName", pjt_projects.Status);
ViewBag.CategoryID = new SelectList(db.pjt_Categories, "pjt_Category_ID", "CatName", pjt_projects.CategoryID);
return View(pjt_projects);
}
View
This shows what I am try to do on the front end. I am getting a error with the bold line in my view code below. The error I am getting is:
There is no ViewData item of type IEnumerable<SelectListItem> that has the key pjt_SubCat_ID.
Code:
<div class="span3 offset1">
#Html.LabelFor(model => model.CategoryID, "Category")
#Html.DropDownList("CategoryID", String.Empty)#*, null, new { #onchange = "FetchSubCategories();" })*#
<br />
#Html.ValidationMessageFor(model => model.CategoryID)
</div>
<div class="span3 offset1">
<label>Sub Category</label>
#Html.DropDownList("pjt_SubCat_ID", String.Empty)
<br />
#Html.ValidationMessageFor(model => model.SubCategoryID)
</div>
Can someone advise me what is going wrong here?
The problem is that the engine is trying to get the SelectList from the viewbag and it cannot find it. I am guessing that you want the Dropdown to display the items you have stored in the viewbag under "pjt_SubCat_ID" but you are not adding that item to the viewbag anywhere in the code that you have listed in your question.
If that is supposed to be the data returned from the SubCategory() method, you will not find that data in the viewbag and you should have a javascript that calls this method on the click event of the original SelectList (category id one) and binds the returned data to the subcategory one.