I'm trying to achieve a lightning component that recursively calls itself to generate a tree hierarchy with attributtes of a filled map that goes like
Map<Integer,Map<Id,List<Object>>> being first key the level of the tree and second key the parentid of the list of objects retrieved.
My question is: Is it possible to create a component that works like this example?
CustomLightningComponent
<aura:component>
<aura:attribute name="mapObject" type="map"/>
<aura:attribute name="level" type="integer"/>
<aura:attribute name="parentId" type="string"/>
<aura:attribute name="listObject" type="list"/>
<aura:iteration items="listObject" var="obj">
<p>{!obj.Name}</p>
<c:CustomLightningComponent mapObject="{!mapObject}" level="{!v.level}" parentId="{!obj.Id}"/>
</aura:iteration>
</aura:component>
CustomLightningComponentController
({
doInit: function(component, event, helper) {
var map = component.get("v.mapObject");
var level = component.get("v.level");
var parentId = component.get("v.parentId");
var listObjects = map[level][parentId];
//To iterate over next level
component.set("v.level", level++);
//Set list
component.set("v.listObject", listObjects);
}
})
The code is pretty basic just to put an example of what I want to implement.
Is this even possible? Call the same lightning component recursively?
Yes, It's possible to iterate over child component using aura:iteration tag. However, the map you have created looks very complex and lightning doesn't provide very easy access to map and its contents. Instead of such complex map you can create JSON object in javascript(helper) that will definitely reduce the complexity.
Related
On ReasonReact, if I want to render a specific element on a HTML element by id I can use the built-in function renderToElementWithId(ReasonReact.reactElement, Dom.element), for example:
ReactDOMRe.renderToElementWithId(<MyComponent />, "myComponent");
I have multiple <input /> HTML tags, and I want it to be rendered in every <input /> which has a specific data attribute. More specifically, I want that each input which has data-type="tags" on it be rendered by <MyComponent />. On Javascript we could do something like document.querySelectorAll("[data-type=tags]") and iterate the result rendering the components.
Although, I can't find anywhere in the documentation of ReasonReact nor BSB about how to do this. Can someone help me?
Thanks, in advance.
ReasonReact has a ReactDOMRe.render function that takes a Dom.element. You can then define querySelectorAll yourself, if you wish:
[#bs.val] [#bs.scope "document"]
external querySelectorAll : string => Dom.element = "";
querySelectorAll("[data-type=tags]")
|> Js.Array.forEach(element => ReactDOMRe.render(<MyComponent />, element));
Or you can use bs-webapi, which gives you querySelectorAll along with a whole heap of other DOM functions if you need them.
I would like to know if is it possible to define a parent component without specifying which child component to use?
Normally i would create a parent component and use the selector of the child component in the html file
parent-component-1.html:
//some logic
<child-component-1-selector></child-component-1-selector>
//some logic
If i follow this approach i have to define which kind of child component i wanna use. But if i wanna use the parent component multiple times with different child components, i have to copy the logic part and create separate parent-components:
parent-component-1.html:
//some logic
<child-component-1-selector></child-component-1-selector>
//some logic
parent-component-2.html:
//some logic (same as above)
<child-component-2-selector></child-component-2-selector>
//some logic (same as above)
I don't like the approach because i would generate code duplicates. Is there a way to define the parent-component without specifying which child component to render and just 'pass' the child component as an argument?
current approach,
grand-parent-component.html:
<parent-component-1></parent-component-1>
<parent-component-2></parent-component-2>
suggested approach,
grand-parent-component.html:
<parent-component-selector [childcomponent] = "child-component-1"></parent-component-selector>
<parent-component-selector [childcomponent] = "child-component-2"></parent-component-selector>
I hope i have made my self clear about my 'problem'. Maybe you guys can help me and give suggestions about best practices
It sounds like you want to be able to do something like:
<my-custom-panel>
<here-is-one-inner-component>
</my-custom-panel>
And then in another place,
<my-custom-panel>
<some-other-component>
</my-custom-panel>
If i'm reading you right, then you're basically looking at using Angular's content projection.
So, in my example above, I'd write my-custom-panel component to look like this:
#Component({
selector: 'my-custom-panel',
template: `
<div class="wrapper">
<h1>My Heading</h1>
<ng-content></ng-content>
</div>
`
})
export class ....
The trick is that <ng-content> tag, which acts as a marker in the component's template. When using my-custom-panel in another template, any content that appears within the my-custom-panel tag will get projected right next to that <ng-content> tag.
Hopefully, an example will make things clearer. So, in the case of my first example, where the template using my-custom-panel is:
<my-custom-panel>
<here-is-one-inner-component>
</my-custom-panel>
That will get transformed into:
<div class="wrapper">
<h1>My Heading</h1>
<ng-content></ng-content>
<here-is-one-inner-component>
</div>
Is that what you're looking for?
I have an issue where I have a StrictBlock within a StreamField:
class DetailsTableBlock(StructBlock):
title = CharBlock(required=False)
description = RichTextBlock(required=False)
table = TableBlock(template="home/blocks/table.html")
class MainStreamBlock(StreamBlock):
....
table = DetailsTableBlock()
The problem occurs when I try to render the table using:
{{ child.value.table }}
all I get is:
{u'data': [[u'test', u'test', u'test'], [u'123', u'asd', u'asd'], [u'123', u'asd', u'asd']], u'first_row_is_table_header': True, u'first_col_is_header': False}
So the question is how can I render html using a StructBlock inside a StreamField? I am using Wagtail 1.7
You should use: {{ child.value.bound_blocks.table }}
The full explanation is given at wagtail documentation, but in short: when you're looping over the content of a StreamField to output it, you'll sometimes get the raw data value, and sometimes get a BoundBlock object which knows both the value and how to render it as HTML. When you access the child values of a StructBlock, you get the raw values (since this is usually the more useful thing to access inside a StructBlock template) - to get the BoundBlock object, you need to read it from the StructBlock's bound_blocks dictionary instead.
I'm new to Salesforce/Apex and I need to be able to test a component I am working on in a separate page.
Here is the scenario. I have the following test page:
<apex:page sidebar="false" showHeader="false" standardController="Contact">
<div id="wrapper" style="max-width:980px;">
<c:djEmailTemplate_MainComponent sObject="{!Contact}" theContactId="{!Contact.Id}"/>
</div>
</apex:page>
I can display the page by adding /apex/testpage to the url after the project name.
What I don't know how to do is to include data to satisfy the parameters (sObject, theContactId) that are needed to populate values in the component.
Can anyone explain how I can do this?
Thanks in advance.
Your test page uses the Contact object as its standard controller, so in most cases you would want to specify a Contact record for the page/controller to operate on. You can use any existing Contact record in your org, or create a new one (specifically you'll want to grab the ID of the record) and then append the ID to the URL you're using like so: /apex/testpage?id=003xxxxxxxxxxxx. This will provide the page and controller a record to pass to the VF component.
I have made an adf tree but I am not able to add links to each child node.
You didn't mentioned that whether or not you are in WebCenter Portal application. But if you are in Portal Application you can take help of NavigationContext for navigation, you can find more information and examples in the documentation. Also you can use NavigationContext from backing bean. You could define actionListener of your commandLink and from that method you can navigate to the various pages from backend as well as from the jspx page.
If you are not in Portal application, in Fusion Web Application you should define your navigation by control-flow-case of adfc-config.xml. Don't use FacesConfig for navigation. Read this documentation to know how navigation system works.
Since you are in a Tree Model and if you need to parameter then you can set some value to session as:
<af:tree value="#{ConnectorTest.model}" var="node" >
<af:commandLink text="#{node.text}" action="#{node.action}">
<af:setPropertyListener from="#{node.value}" to="#{sessionScope.value}" type="action"/>
</af:commandLink>
</af:tree>
here the action will be defined in adfc-config. If you don't need to pass parameter then ignore the af:setPropertyListener but you should define the action in config file.
Hope this will help.
Edit:
Suppose you have two pages: Page1.jspx and Page2.jspx. Now you need to define the action (specifically from-action) in adfc-config.xml as following way:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<adfc-config xmlns="http://xmlns.oracle.com/adf/controller" version="1.2">
<view id="p1">
<page>/path-to-the/Page1.jspx</page>
</view>
<view id="p2">
<page>/path-to-the/Page2.jspx</page>
</view>
<control-flow-rule>
<from-activity-id>p1</from-activity-id>
<control-flow-case>
<from-outcome>goToP2</from-outcome>
<to-activity-id>p2</to-activity-id>
</control-flow-case>
</control-flow-rule>
</adfc-config>
Now if you have a commandLink:
<af:commandLink id="link" action="goToP2" /> will navigate you to the Page2.jspx. The action attribute also accept el expression.
Have u mean to add hyperlink on child node?
<af:tree var="node" value="#{myBean.myTree.root}" id="t1" focusListener="#{myBean.eventMethod}">
<af:commandLink text="#{node.firstname}" />
</af:tree>
when u click on node it fire focus event and call method eventMethod that accepts FocusEvent obj as arguments, in this method u set navigation rule etc etc.....
try it
You can use the <af:switcher> tag, if you want to display different action, for different child nodes