MODX revolution: get second level children - modx-revolution

I've got url: somesite.com/mypage?clinic=21&spec=myspecialisation
In my structure I have clinic -> parent -> final resource to sort out
I have this:
[[!getPage?
&elementClass=`modSnippet`
&element=`getResources`
&parents=`10,15,12`
&resources=`-7,-8`
&depth=`2`
&limit=`21`
&pageVarKey=`page`
&includeTVs=`1`
&includeContent=`1`
&tpl=`pageAllDoctors`
&hideContainers=`true`
&sortby=`FIELD(modResource.id, 456,331,390,491,2756,505,634,699,941,1044,1377,1436,1449,1678,1722,1711,1828,2007,2094,2184,2324,2487,2527)`
&where=`[{"introtext:LIKE":"%[[!searchFieldClinic? &field=`spec`]]%", "AND:template:=":104}]`]]
[[+total:is=``:then=` nothing found.<br/><br/><br/>`:else=``]]
It sorts out the pages with introtext taken from url &spec=myspecialisation perfectly fine
Problem: The &parents=10,15,12 list in the getPage statement should be the list of pages that are children of the pages that are specified in clinic=21 parameter in url
How can I do that?
Thanks a lot in advance.

&parents='21' &hideContainers='1'
You will hide children of clinic, which are parents of other resources. And maybe you should increase &depth

Related

Prestashop all translatable-field display none for product page

Just new in Prestashop (1.6.0.6), I've a problem with my product page in admin. All translatable-field are to display:none (I inspect the code with chrome).
So when I want to create a new product I can't because the name field is required.
I thought that it was simple to find the .js whose do that but it isn't.
If somebody could help me, I would be happy.
Thank you for your help
Hi,
I make some searches and see that the function hideOtherLanguage(id) hide and show translatable-field element.
function hideOtherLanguage(id)
{
console.log(id_language);
$('.translatable-field').hide();
$('.lang-' + id).show();
var id_old_language = id_language;
id_language = id;
if (id_old_language != id)
changeEmployeeLanguage();
updateCurrentText();
}
When I set the Id to 1 (default language), it works. It seems that when I load the page, the function is called twice and the last calling, the id value is undefined. So the show() function will not work.
If somebody could help me. Thank you.
In my console, I see only one error
undefined is not a function.
under index.php / Line 1002
...
$("#product_form").validate({
...
But I find the form.tpl template and set this lines in comment but nothing change.
EDIT: According to comment on this link http://forge.prestashop.com/browse/PSCFV-2928 this can possibly be caused by corrupted installation file(s) - so when on clean install - try to re-download and reinstall...
...otherwise:
I got into a similar problem - in module admin page, when creating configuration form using PrestaShop's HelperForm. I will provide most probable cases and their possible solutions.
The solution for HelperForm was tested on PS 1.6.0.14
Generally there are 2 cases when this will happen.
First, you have to check what html you recieve.
=> Display source code - NOT in developer tools/firebug/etc...!
=> I really mean the pure recieved (JavaScript untouched) html.
Check if your translatable-fields have already the inline style "display: none":
Case 1 - fields already have inline style(s) for "display: none"
This means the template/html was already prepared this way - most probably in some TPL file I saw codes similar to these:
<div class="translatable-field lang-{$language.id_lang}"
{if $language.id_lang != $id_lang_default}style="display:none"{/if}>
Or particularly in HelperForm template:
<div class="translatable-field lang-{$language.id_lang}"
{if $language.id_lang != $defaultFormLanguage}style="display:none"{/if}>
Case 1 is the most easy to solve, you just have to find, where to set this default language.
Solutions
HelperForm
Look where you've (or someone else) prepared the HelperForm object - something like:
$formHelper = new HelperForm();
...
Somewhere there will be something like $formHelper->default_form_language = ...;
My wrong first solution was to get default form language from context - which might not be set:
$this->context->controller->default_form_language; //THIS IS WRONG!
The correct way is to get the default language from configuration - something like:
$default_lang = new Language((int)Configuration::get('PS_LANG_DEFAULT'));
$formHelper->default_form_language = $default_lang->id;
...this particularly solved my problem...
Other form-creations
If there is something else than HelperForm used for form creations, the problem is still very similar.
You have to find where in files(probably tpls) is a condition for printing display:none for your case - then find where is the check-against-variable set and set it correctly yourself.
Case 2 - fields don't have inline style(s) for "display: none"
This means it is done after loading HTML by JavaScript. There are two options:
There is a call for hideOtherLanguage(), but there is wrongly set input language - that means no language will be displayed and all hidden.Solution for this one can be often solved by solving Case 1 (see above). In addition there can be programming error in not setting the after-used language id variable at all... then you would have to set it yourself (assign in JavaScript).
Some script calls some sort of .hide() on .translatable-field - you will have to search for it the hard way and remove/comment it out.
PS: Of course you can set the language to whatever you want, it is just common to set it to default language, because it is the most easier and the most clear way how to set it.

How can I get children of a node?

How can I get all the children for the News item (in the standard project) in a partialview (razor)?
I've tried:
#{
var homePage = CurrentPage.AncestorsOrSelf(1).First();
var newsItems = homePage.Children.Where(x => x.GetProperty("Name").Value == "News");
}
But I get an error that states I can't do lambda expression, whitout casting it. "News" is a node in my webpage holding children and I want to create a macro listing the children. How and what can I cast it to?
Currently, you are looking for children of the home page, named "News". I think you want to go one level deeper.
I reccomend this approach:
// 1- Get root node
var site = Model.Content.AncestorOrSelf("Site");
// 2- Get news node
var news = site.Descendant("News");
var newsItems = news.Children;
Here you use the document type alias to traverse your tree, this is much more reliable than using names, as those can change. This of course may require to rework some elements.
Hope this helps!
Try this to get all of the news nodes that are children of homepage:
var newsItems = homePage.Children.Where("Name = #0", "News");
Then iterate through the children of News:
foreach (var newsChild in newsItems)
You could skip the first step if you already know the ID of your news node like so:
var newsNode = Umbraco.Content(1234);
This page has plenty of examples:
http://our.umbraco.org/documentation/reference/querying/DynamicNode/Collections#

Render flux:field.inline.fal from page in content

I have defined a a FAL resource in my page template
<flux:field.inline.fal name="imageLinkboxMenu"
clear="true"
label="FAL image"
showThumbs="true"
allowedExtensions="jpg,jpeg,gif,png"
maxItems="1"/>
Now i want display this image in a conent element which refers to this page. I'm not able to get the page resource. I tried a
<flux:form.data field="tx_fed_page_flexform" table="pages" uid="{root}" as="fluxPageData">
{fluxPageData.imageLinkboxMenu}
</flux:form.data>
Which only returns 1. I also tried to acces the field via v:page.resource.fal which can not work from my point of view since this does not extract the data from the XML
<v:resource.image identifier="{v:page.resources.fal(field: 'imageLinkboxMenu') -> v:iterator.extract(key: 'id') -> v:iterator.first()}" as="resources" />
Any hints for me?
After some trial and error I finally got it work. The trick was to add to uid of the page. So I ended up with something like
<v:resource.image identifier="{v:page.resources.fal(field: 'imageLinkboxLogo', uid: '{root}') -> v:iterator.extract(key: 'id')}" />
I don't now why but it not work for some translation pages. I receive empty area. Aslo here https://fluidtypo3.org/viewhelpers/flux/master/Field/Inline/FalViewHelper.html we see Usage warning. So i recommend alternatively, you could use <flux:field.file>.

Umbraco AncestorOrSelf(int) - what does it do?

When using:
#Model.AncestorOrSelf(3)
In a .cshtml template in Umbraco, this would presumably limit the node traversal to 3 levels. Is this correct, and if so can anyone also confirm if the current node has the index zero?
#Model.AncestorOrSelf(3)
Model.Content is the current page that we're on. AncestorsOrSelf is all
of the ancestors this page has in the tree. (level) means: go up to
level 1/2/3/... and stop looking for more ancestors when you get
there.
Above is the comment that you get with Umbraco 7.x rc version.
Take an example of the content tree below that is kind of similar to that you normally see in contents section in umbraco admin area:
Each content document has a level and by default it starts with 1.
In a .cshtml template in Umbraco, this would presumably limit the node
traversal to 3 levels
As you can see in the example below, the level gets on increasing - level + 1. so, it starts by 1 and then just go on adding 1 to your sub levels.
- Content
-- Home (level = 1)
-- About Us (level = 2)
-- Contact Us (level = 2)
-- News Area (level = 2)
-- News Item 1 (level = 3)
-- News Item 2 (level = 3)
-- Other Node (level = 1)
So when you mention 3 as parameter for AncestorOrSelf, you are asking to move to 3rd level in the tree from the current element that can be any document/partial view and stop looking for any more ancestors when its found.
AncestorOrSelf(level) returns a single item which if of type DynamicPublishContent i.e. you will have access to many properties like id, name, url, etc.
#CurrentPage.AncestorOrSelf(1)
// based on content structure above, the above statement will give you an item - Home.
It is basically for fetching ancestors by level, doesn't matter what your current level or currentpage object is.
For example, if you want to create a navigation in your main layout so as to share it on all pages of your site, you will do something like this in your template:
<ul>
#foreach(var page in #CurrentPage.AncestorOrSelf(1).Children)
{
<li>#page.Name</li>
}
</ul>
Based on our example, it will give you:
About Us, Contact Us, News Area (in list form and with proper links)
Adding to the answer from SiddharthP I think the OP is possibly looking for the #CurrentPage.Up(int) method - this is traverses up the tree from the current level by the specified amount of levels.
So if you want the grandfather of the current node - #CurrentPage.Up(2) or #Model.Content.Up(2) for the strongly typed version.
Think of it as Ancestor starts from the root of the content tree down and Up starts from where you are going towards the root.
I think the confusing bit is you use the CurrentPage object but start traversing from the top root node towards the CurrentPage. When we think of our Ancestors in humanity we don't start from the beginning of time!
If my understanding of the code is correct, .AncestorOrSelf(int) returns the ancestor (or self) of a node at the given level in the argument.
Taken from lines 948 & 956 of https://github.com/umbraco/Umbraco-CMS/blob/6.2.0/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs
public DynamicNode AncestorOrSelf(int level)
{
return AncestorOrSelf(node => node.Level == level);
}
public DynamicNode AncestorOrSelf(Func<DynamicNode, bool> func)
{
if (func(this)) return this;
var content = this;
while (content.Level > 1) // while we have a parent, consider the parent
{
// see note in .Parent - strange things can happen
var parent = content.Parent;
if (parent == content) return null;
content = parent;
if (func(content))
return content;
}
return null;
}
Hope I've understood that correctly and that this helps.

umbraco - how to get all of nodes by Document Type

How can I get all nodes by specific Document Type?
For example, I want to get in code behind all of nodes with Document Type: s3Article. How can I do this?
New informations:
IEnumerable<Node> nodes = uQuery.GetNodesByType("s3Article").Where(x => x.NiceUrl.Contains("en"));
lvArticles.DataSource = nodes;
lvArticles.DataBind();
This is my code. I had to use Where(x => x.NiceUrl.Contains("en")), because I have 2 language version- without Where I receive nodes from all catalogues with doctype s3Article, but I want to get only from one language version.
Problem is here:
<a href='<%# umbraco.library.NiceUrl(Tools.NumericTools.tryParseInt( Eval("id"))) %>'><%# Eval("title")%></a>
<%# Tools.TextTools.makeIMGHTML("../.."+ Eval("img").ToString(),"180") %>
<%# umbraco.library.StripHtml(Limit(Eval("Article"), 1000))%>
<%# Eval("author")%>
System.Web.HttpException: DataBinding:
'umbraco.presentation.nodeFactory.Node' does not contain a property named 'title'.
The same problem happens with the title, img, article, author. Only ID works nice. How to resolve it?
You can use the uQuery GetNodesByType(string or int) method:
IEnumerable<Node> nodes = uQuery.GetNodesByType("s3Article");
Alternatively, you can use an extension method to get all descendant nodes and then query them by type as in the following answer:
Umbraco 4.6+ - How to get all nodes by doctype in C#?
You could use this to databind to a control within a usercontrol like so:
lvArticles.DataSource = nodes.Select(n => new {
ID: n.Id,
Title: n.GetProperty("title").Value,
Author: n.GetProperty("author").Value,
Article: n.GetProperty("article").Value,
Image: n.GetProperty("img").Value,
});
lvArticles.DataBind();
Only you would need to strip the html, convert the image id to a url, etc. within the select statement as well...
As Shannon Deminick mentions, uQuery is somewhat obsolete. ExamineManager will be the fastest execution time. https://our.umbraco.org/forum/developers/api-questions/45777-uQuery-vs-Examine-vs-IPublishedContent-for-Querying
I also found it to be the easiest and most readable approach to use ExamineManager's search builder. Very flexible, and has the added benefit of being very readable due to the Fluent Builder pattern the U Team used.
This will search ALL nodes, so if you need within a specific branch, you can use .ParentId(1234) etc.
var query = ExamineManager.Instance.CreateSearchCriteria()
.NodeTypeAlias("yourDocumentType")
.Compile();
IEnumerable<IPublishedContent> myNodes = Umbraco.TypedSearch(query);
I prefer typed nodes, but you can also just use "Search()" instead of "TypedSearch()" if you prefer dynamic nodes.
Another example including a specific property value "myPropValue" == "ABC",
var query = ExamineManager.Instance.CreateSearchCriteria()
.NodeTypeAlias("yourDocumentType")
.Or() //Other predicate .And, .Not etc.
.Field("myPropValue", "ABC")
.Compile();
Ref - https://our.umbraco.org/documentation/reference/querying/umbracohelper/

Resources