Display Child field at vfp from Controller - salesforce

I'm trying to display subqueries columns on my Visualforce page but I can't.
Apex controller:
public class FormController {
private final FormularioDeVisita__c formulario;
public FormularioVisitaPdfController() {
if(ApexPages.currentPage().getParameters().get('id') != null){
formulario = [
SELECT
ChequeEmpresa__c, SedePropria__c, CNPJ__c, MercadoExternoCliente__c, DataFundacao__c,
(SELECT
FormInfoPercent__c, FormInfoText__c, FormInfoCheckbox__c, FormInfoDate__c, FormInfoCurrency__c,
FormInfoPercentDecimal__c, FormularioVisita__c
from FormularioVisitaChild__r)
from FormularioDeVisita__c
WHERE Id = :ApexPages.currentPage().getParameters().get('id')];
}
}
public FormularioDeVisita__c getformularioVisita() {
return formulario;
}
public PageReference save() {
update formulario;
return null;
}
}
Example from Visualforce page:
<tr>
<td class="table td">Mercado livre?</td>
<td class="table td_right">{!formularioVisita.MercadoLivre__c}</td>
</tr>
Using like that I can display the columns from the father without problems, but when I try to display from children, I can't.
I didn't find any information about it.
Display children columns in my HTML in Visualforce.

You need <apex:repeat>, <apex:datatable>, <apex:pageBlockTable> tags.
https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_repeat.htm contains example of using repeat to access Account.Cases. In your code it'll be repeat over {!formularioVisita.FormularioVisitaChild__r}

Related

error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays how to solve

Service code which return json data
export class EmployeeServiceService {
constructor(private _http:Http) { }
GetEmployees() :Observable<IEmployee[]>{
debugger;
return this._http.get("http://localhost:2724/api/employee/1")
.map((response:Response)=> <IEmployee[]>response.json())
}
}
In this component class im not able to convert the json data please any one help me to solve my issue
export class EmployeeListComponent implements OnInit {
Employees:IEmployee[];
constructor( private _EmployeeService: EmployeeServiceService) {
}
ngOnInit() {
this._EmployeeService
.GetEmployees().subscribe((employeeData)=> this.Employees = employeeData);
}
}
html
<tbody>
<tr *ngFor="let employee of Employees">
<td>{{employee.Address}}</td>
<td>{{employee.City}}</td>
<td>{{employee.EmployeeID}}</td>
<td>{{employee.FirstName}}</td>
<td>{{employee.LastName}}</td>
</tr>
<tr *ngIf="!Employees|| Employees.length== 0">
<td>No employee to display!!!</td>
</tr>
</tbody>
enter code here
This error occurs whenever you are trying to bind an Object with ngFor. ngFor directive supports only arrays.
As per the request, it seems it returns only one Object,
return this._http.get("http://localhost:2724/api/employee/1")
if you need to bind only one Object no need to use ngFor.
Also you need to initialize employees with an empty array.
Employees:IEmployee[] = [];
if you still want to bind one Object to the table, push the Object to the array as follows,
this.Employees.push(employeeData);
Two options
(i) Change your request to return all employees
return this._http.get("http://localhost:2724/api/employee/all")
(ii) Push the Object to an array as follows,
ngOnInit() {
this._EmployeeService
.GetEmployees().subscribe((employeeData)=> this.Employees.push(employeeData);
}

Grails GSP Loop through an index and do somthing with selected lines

In an Index-gsp, I want to be able to select an arbitrary number of lines and then by clicking a link send all those lines to a controller for processing e.g. creating new objects of a different kind.
I've no idea how selection can be done or how to collect these selected lines in a GSP. Maybe I should use a checkbox on each line if that's possible?
It's a list of products which is displayed using a modified index.gsp.
Each product-line has a checkbox in front.
What I want is to make a list of the products that are checked an then transmit this list to a controller.
a part of this index.gsp:
<li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
<li><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
<li><g:link class="create" action="createOffer"><g:message code="default.new.label" args="[entityName]" params="toOffer" /></g:link></li>
</ul>
</div>
<div id="list-prodBuffer" class="content scaffold-list" role="main">
<h1><g:message code="default.list.label" args="[entityName]" /></h1>
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<table>
<thead>
<tr>
<td> Välj</td>
<td> ID</td>
</tr>
</thead>
<tbody>
<g:each in="${prodBufferList}" status="i" var="prodBuffer">
<tr class="${ (i % 2) == 0 ? 'even': 'odd'}">
<td><g:checkBox name="toOffer" value="${prodBuffer.id}" checked="false" /></td>
<td>${prodBuffer.id}</td>
So this not an ordinary form, just a list where I want to use a link to transmit it to the controller.
I'm a beginner and have no idea how to do it.
You can collect all necessary data from page using javascript, and then send all data to your controller for processing.
There are a lot of ways to do it.
For example send via JQuery:
<script>
//some code
var items = [1,2,3];
//some code
$('#add-location').click(function () {
$.ajax({
type: "POST",
url: "${g.createLink(controller:'myController', action: 'myControllerMethod')}",
data: {items: items},
success: function (data) {
console.log(data)
}
});
});
</script>
I will answer this but have to slow down since it feels like i am beginning to write your project:
In gsp you will need to have a hidden field followed by a check box amongst data you are trying to capture, checkbox should contain all the data elements required to build your output.
<g:hiddenField name="userSelection" value=""/>
<g:checkBox name="myCheckBox" id='myCheckBox' value="${instance.id}"
data-field1="${instance.field1}" data-field1="${instance.field1}"
checked="${instance.userSelected?.contains(instance.id)?true:false}" />
In the java script segment of the page you will need to add the following
This will then auto select selection and add to javascript array
// Customized collection of elements used by both selection and search form
$.fn.serializeObject = function() {
if ($("[name='myCheckBox']:checked").size()>0) {
var data=[]
$("[name='myCheckBox']:checked").each(function() {
var field1=$(this).data('field1');
var field2=$(this).data('field2');
data.push({id: this.value, field1:field1, field2:field2 });
});
return data
}
};
Most importantly will your data sit across many different gsp listing pages if so you will need to hack pagination:
//Modify pagination now to capture
$(".pagination a").click(function() {
var currentUrl=$(this).attr('href');
var parsedUrl=$(this).attr('href', currentUrl.replace(/\&userSelection=.*&/, '&').replace(/\&userSelection=\&/, '&'));
var newUrl=parsedUrl.attr('href') + '&userSelection=' + encodeURIComponent($('#userSelection').val());
window.location.href=newUrl
return false;
});
Then in the controller parse the JSON form field and make it into what you want when posted
def u=[]
def m=[:]
if (params.userSelection) {
def item=JSON.parse(params.userSelection)
item?.each {JSONObject i->
// When field1 is null in JSON set it as null properly
if (JSONObject.NULL.equals(i.field1)) {
i.field1=null
}
if (resultsGroup) {
if (!resultsGroup.contains(i.id as Long)) {
u << i
}
} else {
u << i
}
}
m.userSelected=item?.collect{it.id as Long}
m.results=u
}
return m

Unable to access merge field values inside visualforce component in angularJs

View:
<div ng-controller = "ClPortalRegistrationController">
<div ng-repeat="(key, value) in ObjectApiFieldsetMap">
{{key}} {{value}} //this is printing correct result
<c:FieldSetComponent objectAPIName="'{{key}}'" fieldSet="'{{value}}'" cid="'{{key}}'"
sectionTitle="Section 1" columns="2" textAlign="center"></c:FieldSetComponent>
</div>
</div>
Controller:
$scope.ObjectApiFieldsetMap = {
Applications__c: "Application_FieldSet_One",
clcommon__Collateral__c: "Collateral_FieldSet_One"
};
Now when I'm trying to access {{key}},{{value}} inside c:FieldSetComponent ,its only passing string as {{key}} and {{value}} and not the converted result. How can I access values stored inside key, value inside component?
Posting the solution which I implemented as a work around.
Turns out that you cannot access angular merge field values inside visualforce components. So instead of manipulating(segregating input into key-value pair) values inside angular controller, I have to push the logic to apex controller.
<apex:component controller="RegistrationController" access="global">
<apex:repeat value="{!ObjectApiFieldsetMap}" var="apiName">
<c:FieldSetComponent objectAPIName="{!apiName}" fieldSet="{!ObjectApiFieldsetMap[apiName]}"
cid="{!apiName}{!ObjectApiFieldsetMap[apiName]}"
columns="1" textAlign="center">
</c:FieldSetComponent>
</apex:repeat>
</apex:component>
And in my apex controller i.e RegistrationController , I have set the logic to segregate key values from a map input which I'm using inside visualforce component
global class RegistrationController {
global Map<String,String> ObjectApiFieldsetMap {
get {
ObjectApiFieldsetMap = arrangeApiFieldSetsByOrder();
return ObjectApiFieldsetMap;
}
set;
}
global Map<String,String> arrangeApiFieldSetsByOrder() {
Map<String,String> ObjectApiFieldsetMap = new Map<String,String>();
/* logic for segregation */
return ObjectApiFieldsetMap;
}
}

Conditional css class assign in angular 2

I have a grid with checkbox, I am putting checked values in an array (currentFocusedRow), now I want to assign activeRow class to the checked row:
// app.ts
class contact {
public contactlist = [{icontact_id: "contact1"}, {icontact_id: "contact2"}, {icontact_id: "contact3"}, {...}];
public currentFocusedRow = ["contact2", "contact3"];
}
// app.html
<tr *ngFor="let contact of contactlist"
[class.activeRow]="contact.icontact_id == currentFocusedRow">
...
</tr>
now since currentFocusedRow is an array i can't simply check like that (contact.icontact_id == currentFocusedRow) there should be something to check if the value is present in that array or not like indexOf.
I think this should work for you:
Typescript
isActive(id) {
return this.currentFocusedRow.indexOf(id) !== -1
}
HTML
<tr *ngFor="let contact of contactlist"
[class.activeRow]="isActive(contact.icontact_id)">
</tr>
You can use index of the object that is current object, by using:
<tr *ngFor="let contact of contactlist; let i = index">
Which will enable you to get those indexes.
Apart from that, you can just use NgClass directive.
Checking with indexOf in directive itself worked, this is pretty amazing that we can use this JS methods directly in DOM:
<tr *ngFor="let contact of contactlist;"
[class.activeRow]="currentFocusedRow.indexOf(contact.icontact_id) != '-1'">
</tr>

How to ng-repeat into html table with multiple levels of json?

I have an object of social media stats. I'm trying to ng-repeat them into a table. Here's my plunker.
HTML:
<table>
<tr ng-repeat="(metric, metricData) in data">
<td>{{metric}}</td>
<td>{{metricData}}</td>
</tr>
</table>
Controller object:
$scope.data = { buzz:0,
Delicious:121,
Facebook:
{
like_count: "6266",
share_count: "20746"
},
GooglePlusOne:429,
LinkedIn:820,
Twitter:4074
};
I run into a problem when I get to the Facebook results. Within the <td> that entire object gets displayed (as it should be with how I have my code setup). But what I'd rather have happen is to repeat through that object and display the key and value in the cell.
I tried doing something looking to see if metricData is an object and doing some sort of ng-repeat on that. But I wasn't having luck with that. Any idea on how I can display the inner object (keys & value) within the cells?
You can define a scope function returning the type of metricData :
$scope.typeOf = function(input) {
return typeof input;
}
And then you can display it according to its type :
<tr ng-repeat="(metric, metricData) in data">
<td>{{metric}}</td>
<td ng-switch on="typeOf(metricData)">
<div ng-switch-when="object">
<div ng-repeat="(key, value) in metricData">
<span>{{key}}</span>
<span>{{value}}</span>
</div>
</div>
<span ng-switch-default>{{metricData}}</span>
</td>
</tr>
You can see it in this Plunker
Sounds like you'll need a specific directive that wires up children to be recursive, take a look at this example: Recursion in Angular directives
What you'd check on is if what you need to repeat is an object and not a value, then add the new element compile it, and start the process over again.
I'm assuming you want each of those values to have their own line but you don't explain exactly how you want it to work. I think the matter would best be handled by passing a clean version of what you want to the ng-repeat directive. I'm assuming you want two rows for facebook in your sample. You could create a filter to flatten the metrics so there are properties "Facebook_like_count" and "Facebook_share_count" (PLUNKER):
app.filter('flatten', function() {
function flattenTo(source, dest, predicate) {
predicate = predicate || '';
angular.forEach(source, function(value, key) {
if (typeof(value) == 'object') {
flattenTo(value, dest, predicate + key + '_');
} else {
dest[predicate + key] = value;
}
});
}
return function(input) {
var obj = {};
flattenTo(input, obj, '');
return obj;
}
});
Then your repeat can use the filter:
<tr ng-repeat="(metric, metricData) in data|flatten">

Resources