I'm new to the new umbraco grid functionality and I have a question about it.
I have a page with an article where I use the grid functionality to show some image and text besides that image. This is working fine.
In the properties of that page I have put a checkbox for saying that the article is for sale or not, when checked the product should automatically appear on a for sale page.
I can get the product that is for sale on that page, but now I also want to show the image and text on that page. I've created a List with a custom viewmodel to hold the content for every product that is for sale. The problem is with providing the JObject to the GetGridHtml function. This function wants a string and I'm providing the property which results in an error.
What is the best way to get the content for the grid to show on that separate page?
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
var home = CurrentPage.Site();
List<ForSaleItemsViewModel> forSaleItemsVM = new List<ForSaleItemsViewModel>();
if(home.Children.Any())
{
foreach(var childPage in home.Children)
{
if(childPage.Children.Any())
{
foreach(var child in childPage.Children)
{
if(child.HasProperty("ForSale") && child.ForSale)
{
forSaleItemsVM.Add(new ForSaleItemsViewModel
{
ID = 1,
Content = child.Content,
Sold = child.Sold
});
}
}
}
}
}
}
<div class="container">
#foreach(var item in forSaleItemsVM)
{
if (item.Sold)
{
<span>SOLD!</span>
}
CurrentPage.GetGridHtml(item.Content.ToString(), "bootstrap3");
}
</div>
According to the Umbraco forum it is not possible to do this. I got this answer:
If you see the documentation for best pratices for the grid layout
https://our.umbraco.org/Documentation/Using-Umbraco/Backoffice-Overview/Property-Editors/Built-in-Property-Editors-v7/Grid-Layout-Best-Practices
there is a chapter about the limitations for the grid layout
https://our.umbraco.org/Documentation/Using-Umbraco/Backoffice-Overview/Property-Editors/Built-in-Property-Editors-v7/Grid-Layout-Best-Practices#Limitations.
And of the limitions of using the grid layout is that it´s not for
reused content.
It says - There is no managed api to drill into the grid content and
target specific cell content - so a grid layout is not a recommended
storage of reusable content - it simply wasn't designed for this
scenario. If you wish to reuse content in multiple pages, it is still
recommended that you store these pieces of content as seperate content
nodes, so they can be stored, cached and queried as usual.
Related
Does anyone know if there is a way within Kentico CMS to nest a webpart within another webpart? I did a little research and I don't see many results on the topic so it seems the short answer is no, but maybe there is a workaround? On the project I am working on it is a requirement that the content author is able to place a hamburger menu on the page and then add other content within that hamburger menu via drag and drop. How can this be achieved within Kentico?
Thanks.
Typically a web part consists of user controls and not nested web parts. Take a look at the CMSRepeater for instance. It sets properties of a user control created by Kentico.
For what you're explaining it seems like you want a custom web part with widget zones in it. Those widget zones will allow you to drag and drop content in place (what content I have no idea really because you can't drag and drop content in Kentico, only areas/widgets).
For navigation, you might want to look at creating it based on the content tree but maybe a hamburger menu is not for navigation in your case.
The solution was to add a widget zone within the web-part.
Circling back to this post. Although adding a <cms:CMSEditableRegion /> tag to the page did indeed allow me to nest a Widget within a Webpart zone, it seemed a bit unnecessary for the user to have to switch between the design tab and page tab in order to achieve adding a nested component, not to mention having to register every webpart as a widget; quite unnecessary. I noticed Kentico's built in Layout webpart allowed for nested webparts so I looked at the code and was finally able to figure out how to implemented nesting a webpart within another webpart!
Ensure your webpart's code-behind inherits from CMSAbstractLayoutWebPart
Add the following method to your code-behind:
protected override void PrepareLayout()
{
StartLayout();
Append("<div");
Append(" style=\"width: ", "100%", "\"");
if (IsDesign)
{
Append(" id=\"", ShortClientID, "_env\">");
Append("<table class=\"LayoutTable\" cellspacing=\"0\" style=\"width: 100%;\">");
if (ViewModeIsDesign())
{
Append("<tr><td class=\"LayoutHeader\" colspan=\"2\">");
// Add header container
AddHeaderContainer();
Append("</td></tr>");
}
Append("<tr><td id=\"", ShortClientID, "_info\" style=\"width: 100%;\">");
}
else
{
Append(">");
}
// Add the tabs
var acc = new CMSAccordion();
acc.ID = ID + "acc";
AddControl(acc);
if (IsDesign)
{
Append("</td>");
if (AllowDesignMode)
{
// Width resizer
Append("<td class=\"HorizontalResizer\" onmousedown=\"" + GetHorizontalResizerScript("env", "Width", false, "info") + " return false;\"> </td>");
}
Append("</tr>");
}
// Pane headers
string[] headers = TextHelper.EnsureLineEndings("HEADER", "\n").Split('\n');
// Create new pane
var pane = new CMSAccordionPane();
pane.ID = ID + "pane";
pane.Header = new TextTransformationTemplate(string.Empty);
acc.Panes.Add(pane);
pane.WebPartZone = AddZone(ID + "-ContentArea", ID + "-ContentArea", pane.ContentContainer);
acc.SelectedIndex = 1;
if (IsDesign)
{
if (AllowDesignMode)
{
Append("<tr><td class=\"LayoutFooter cms-bootstrap\" colspan=\"2\"><div class=\"LayoutFooterContent\">");
// Pane actions
Append("<div class=\"LayoutLeftActions\">");
Append("</div></div></td></tr>");
}
Append("</table>");
}
Append("</div>");
FinishLayout();
}
I have following viewpage , Its form that contains text field, dropdowns and Rich text areas.
this is the cshtml code for that viewpage
I want to restrict Product_ID, ProductTypeID, ProductCategoryID, Subsidary_ID to first page and from Product title onward add to second page .
like this view
How can I do this ?
You would need to create 3 separate view models with 3 separate views and 3 actions methods. Then in the POST method for the 1st view, save the data and redirect to the 2nd view as so on. Assuming you want the visual effect of only displaying a limited number of form controls in the view, a better solution would be to keep one view and inside the form tags, rendered sections with 'next/back' buttons to display only one section at a time. A simple example would be
View
<section>
// first section controls
<button class="next">Next</button>
</section>
<section>
// second section controls
<button class="next">Next</button>
</section>
CSS
section:not(:first-of-type) {
display:none;
}
Script
$('.next').click(function () {
var container = $(this).closest('section');
container.next('section').show();
container.hide();
});
With the last section in the form containing a submit button to post the form back to the controller.
Refer also this answer for more detail on implementing client side validation to ensure the form controls in the current section are valid before moving to the next section.
Is it possible to loop through list of models and update displayed data in view without refreshing the page or making ajax call to server?
Scenario:
Model:
public SomeModel
{
public int Id { get; set; }
public string LinkName { get; set; }
public string ItemDecsiption { get; set; }
public string Text { get; set; }
}
List of SomeModel objects is inicialized, filled with data and passed to View in controller ActionResult. I can see all data in view (i am able to loop through individual models and create list from SomeModel.LinkName property.
<ul>
<% foreach (SomeNamespace.SomeModel m in Model)
{ %>
<li class="green"><%= m.LinkName %></li>
<% } %>
</ul>
What I want to do is to divide page content section into two parts-one with menu (consisting of links created from every LinkName in Model) and second containing block with description and text (for id currently clicked in menu). Now comes the trick part. I want to be able to change displayed data in second block after clicking Link in menu without refreshing the page or making ajax call to server (since all the data I need is already available to client side). Only solution I could think of is to generate hidden blocks for every SomeModel object and then write jquery to manipulate visibility after link click. What I want to know is if there is some more elegant way to accomplish this.
Project is written in C#.NET 3.5 ASP.NET MVC 2.0
The only way to do this would be to use JavaScript to manipulate the DOM.
Depending on the markup which you'll produce, hidden html blocks may be the most elegant solution of all. Like, for intance, if you switch visibility by simply changing a class of block which should be visible without changing the DOM.
The other option will be to prepare json object from Model and use it as data source for visible markup. But this may lead to raise of complexity which is not necessary in most of the cases.
there is another way.
1.var data=#Model.ToJson() in js; there is not a ToJson function ,that just what you need to do
2.only one content block
3.when click menu,find element in data,and set block content use js
Is there some way in Sitecore 7 when using MVC to create a controller which can return a PartialView result using the rendering defined on the item (or its template standard values), without having to set up Layout and Renderings for that item?
I can see how to do this using custom template fields, but this seems like a hacky way of doing things. Is there a better way to achieve the following:
public PartialViewResult MyAction(string someParameter)
{
Item selectedItem;
//some code here to retrieve sitecore item based on the value of someParameter
var cshtmlFilePath = selectedItem["MyCustomField"];
return PartialView(cshtmlFilePath, selectedItem);
}
FYI my cshtml could be something really simple like:
#model Sitecore.Data.Items.Item
<div>
<h3>
#Html.Sitecore().Field("Title", Model)
</h3>
<div>
#Html.Sitecore().Field("Content", Model)
</div>
</div>
While the approach above will work, I don't like it because there is not a proper interface for assigning the rendering to the item's template's standard values. I could easily define my own presentation template which has a single 'Path' field, then create items somewhere under `sitecore/layout/Renderings' then reference that item in a link field of my content item, but it just seems like that should be doable out of the box.
I'm not sure I fully understand the intent here, so this may only be a partial answer, but seeing as you want to render an item based on layout information contained within the item itself, would Item Renderings be able to help?
Here's the info: http://www.sitecore.net/Community/Technical-Blogs/John-West-Sitecore-Blog/Posts/2012/06/MVC-Item-Renderings-in-the-Sitecore-ASPNET-CMS.aspx
I realize returning a partial view would be a little more flexible than the Item Rendering route, but in the normal scenario (i.e. adding a callout to a page) it seems like this method might work.
One solution is to simply assign a layout (which references a cshtml file) to the item, then use item.Visualization to get the file path to the layout assigned to the item and use that layout's cshtml file in the call to PartialView.
public PartialViewResult MyAction(string contentItem)
{
Item selectedItem;
//retrieve sitecore item
string layoutPath = selectedItem.Visualization.Layout.FilePath;
return PartialView(layoutPath, modalContentItem);
}
As the title says...
If I start my app project with a pivot page(MainPage.xaml) and then choose to click for example the "design two" link in the databinded listbox. Is it possible to bind the "LineThree" text for the "design two" link in to a separate portrait page?
Do I have to make new portrait page for every "LineThree"-link? Or can I just generate the "MainViewModelSampleData.xaml" data to a single portrait page depending on what "LineOne"-link I click in the pivot page in the start?
Hope my question is understandable... :P
If I understand you correctly, you want to have a main page that contains a list of data, and then a details page whose contents are dependent on the item that you clicked in the main page. The answer to your question is then "yes". There are a number of ways to achieve this, some of which include global variables, a custom navigation service, storing a value in isolated storage and so on. My personal preference is to use the context of the NavigationService and to pass an ID or an index in the query string for the target page.
Your call to navigate to the details page then looks like this:
Application.Current.Navigate(string.Format("/Views/DetailsView.xaml?id={0}", id));
In the target page, you override the OnNavigatedTo handler to retrieve the value that you passed and then process it accordingly (i.e. look up the value from your database, or retrieve it from a data collection).
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (this.NavigationContext.QueryString.ContainsKey("id"))
{
var id = this.NavigationContext.QueryString["id"];
// TODO: Do what you need to with the ID.
}
else
{
// I use this condition to handle creating new items.
}
}
How is what you're trying to do different from what is created by default in a new DataBound Application? That lets you select an item in the list on the main page and then displays another page which includes the text from LineThree.
I suggest you look at the sample code created as part of a new DataBound Application.