I see how to pass data in the form of strings from one object to another
What I want to do, however, is pass an object from one vm to another -- is this possible? I can think of these ideas:
Stream the object as json and pass that as a param.
Use an id to look up and create the object
in the receiving vm
Pass the object itself (ideal)
Will any of these work (well, #2 almost certainly will)? If 1 or 3 will work, can you possibly supply (detailed?) instructions on how to do so?
Thanks!!
jesse liberty
Add an parameter in your page constructor like:
public class MyPage : ContentPage
{
public MyPage(Object sth)
{..... }}
Then pass the object with
Navigation.PushAsync(new MyPage(sth));
Put the following at the top of the page that will be receiving the data
[QueryProperty(nameof(CodesToAdd), nameof(CodesToAdd))]
Create a corresponding property (in this case CodesToAdd)
In the setter for that property getg the string value passed to you
_codesToAdd = Uri.UnescapeDataString(value ?? string.Empty);
To send the data (in this case the codes to add) put this in the calling program:
await Shell.Current.GoToAsync($"{nameof(AddWidgetPage)}?CodesToAdd={codesToAddAsString}");
The first part in the parens identifies the page you want to navigate to. The part after the ? is the parameter. Make sure your param name (CodesToAdd) matches the one in your receiving page.
Related
I'm in Laravel 8 with Nova 3.22. I have a table that contains a field that is populated automatically with a serial number inside a DB transaction, and in order to enforce that I have a CreateProduct action defined that wraps the creation of that resource. Everywhere I need to create a new instance of that model, I call the action, and I need to do the same in Nova. I've found the newModel() method to override, but it has two problems.
public static function newModel()
{
$instance = new CreateProduct(
new \App\Models\Sku(), //Placeholder
\App\Models\Product::STATUS_DEFAULT,
null
);
return $instance->handle();
}
Firstly, this method is called on create (displaying the input form) as well as store store operations. This means I end up with two calls to my action, creating spurious serial numbers in my DB. If I don't override newModel like this, it creates records that lack a serial number altogether. I have a choice of 0 or 2 calls, but I only want 1!
The second issue is related; when the form is displayed, it calls newModel, but I have to use placeholder data for required params of the action, as those fields have (obviously) not been set yet, but I need to replace those placeholders with the real submitted values the second time, and I'm not sure how I would do that.
I feel I must be missing something – is there something like newModel, but that is only called for a store operation?
As we are switching to sitecore from a java platform, I have some questions regarding parameters. This is easily done in jsp but I can't find a solution for sitecore. (the implementation is done by external partners)
In my cshtml, I include other elements via the placeholder-function: #Html.Sitecore().Placeholder("Placholdername")
The elements included as a placeholder also can include other elements as placeholders.
So the question is: can I pass some parameters along with those placeholders?
Like my parent element has a certain variable set, for example "i = 5", and I want to pass this variable to the elements included as placeholders and also pass it to the elements included as placeholders in the placeholders?
Something like:
A includes B as a placeholder and passes "i=5" and B includes C as a placeholder and passes "i=5" so in C the value of "i" is "5" because "i" was set to "5" in A.
On out current coremedia platform I can simply use something like:
<cm:include self="${self}" view="asdf">
<cm:param name="i" value="5"/>
</cm:include>
Edit:
What I want to achieve is the following: For example I have the following structure: the page frame cshtml with a variable i=5, which then includes a grid as a placeholder and passes the variable to the grid. The grid then does some math like i=i+5 (which should equal 10) and then includes a teaser as a placeholder and passes the new i=10 to the teaser and so on..
You should set the value of i in the model. Then all the different views or partial views should inherit the same model.
You can assign parameters to renderings, but not to placeholders. Placeholders should be seen as a hole. You can dynamically put stuff in it but you can't assign parameters to it. There's a discussion of that here: https://sitecore.stackexchange.com/questions/2098/add-rendering-parameters-to-placeholder/2101
I can think of at least two approaches to solve your problem:
Although your question is a bit lacking in detail, it kind of looks like you don't necessarily need placeholders because you already know what you're going to render inside those spaces. If that's the case, then you can statically bind your MVC views instead of using placeholders. This is not a common practice, but it is mentioned in Sitecore's latest training material and elsewhere as a way to optimize when you don't need the flexibility of placeholders. This is normally done using the #Html.Sitecore.Rendering helper.
You could use a global variable of sorts by leveraging the good old HttpContext.Items collection.
You can add parameters to the ViewData dictionary, in a controller action method:
public ActionResult MyPage()
{
ContextService.Get().GetCurrent().ViewData.Add("MyKey", "MyValue");
return View();
}
Then, any View Renderings can access the parameter from ViewData:
#{
var value = ViewData["MyKey"].Value;
}
Or if you're using Controller Renderings, add some code to fetch the ViewData from parent pages, and add it to the current ViewData instance:
public ActionResult ChildRendering()
{
// Get any ViewData previously added to this ViewContext
var contextViewData = ContextService.Get().GetCurrent().ViewData;
contextViewData.ToList().ForEach(x => ViewData.Add(x.Key, x.Value));
return View();
}
Your ViewData contents will now be available in view files.
This is discussed in a little more detail here: https://chrisperks.co/2017/03/06/a-workaround-for-missing-viewdata-in-sitecore-mvc/
I'm looking for a function that would tell me the current object and method by way of the URI. Normally, I would use $this->uri->uri_string(), however, I do not want to pass any "dynamic" segments. For example, a URI of 'products/shoes/123', would be 'products/view_product'.
I want to be able to do this so I can create a config file containing page titles... since I use a model to output my page header. It is called from MY_Controller.php in the construct. For example: $this->template->overall_header($title = "View Product")...
but in the construct, it would be:
$this->template->overall_header($title = $this->config->item($object_method_string));
Anybody have any solutions? Thanks for your time.
for current method
$method= $this->router->fetch_method();
I hope you are talking about this
To expand on Nishant's answer you can access the attributes from the router class.
So for current object;
$this->router->class
And for current method;
$this->router->method
I am trying to design a generalized detail page for an object.
In the controller class I find the list of all child relations of that object.
I then want to create for each child relations found and for accomplishing this I will have to dynamically set the value of list attribute within it.
For example :
<apex:relatedList subject={!ObjName} list="{!relatedListName}" />
But the problem here is that list attribute only accepts String literal, so can't implement it. Please suggest a way for this requirement to be accomplished.
Yes, you can dynamically set the value of the "list" attribute on a relatedlist tag, and you do so via Dynamic Visualforce. This question has since been asked and concisely answered here on the Salesforce Stack exchange for any future browsers:
https://salesforce.stackexchange.com/questions/7531/apexrelatedlist-list-dontexistinallorgs-c-only-solveable-with-dynamic
Here is the general solution:
In a custom controller, add a function to dynamically generate the RelatedList markup. I will assume from your wording that you have already accessed the full list of child relationships in your controller, so in order to spit out all the lists in one block, I would use something like this:
public Component.Apex.OutputPanel getDynamicList()
{
Component.Apex.OutputPanel outPanel = new Component.Apex.OutputPanel();
for(String id : childNames) {
Component.Apex.RelatedList relList = new Component.Apex.RelatedList();
relList.list = id;
outPanel.childComponents.add(relList);
}
return outPanel;
}
In the middle there, you can dynamically set any string to the "List" value, and by iterating through your list of strings, you are adding related list objects over and over again. (To simply add one list, remove the for loop, and make the "id" string value whatever specific relationship you wish to display).
Then on your visualforce page, you can render this block out using a dynamic visualforce tag:
<apex:dynamicComponent componentValue="{!DynamicList}" />
(as you may know, the formulaic value field will dig up the getter automatically)
Great success!
I would suggest trying apex:dataTable or apex:repeat to build your own list display. You will likely need a wrapper class to handle passing attributes and values from the sObject to the page.
I have a function searchWorkByName that takes "key" as an argument and use SQOL to retrieve the data.
In visualforce side, I have a link that calls searchWorkByName but would like to be able to pass argument such as character 'a'
example, (this throws an error)
<apex:commandLink value="search!" action="{!searchWorkByName('aaa')}" />
Is it possible to do so if not what is the alternatives?
apex class
public class SearchWorkTest {
public PageReference searchWorkByName(String key) {
//find record of work names starting from provided key character
workNames = [select name from work__c where work__c.name like 'key%'];
return Page.searchResult;
}
}
visualforce
<apex:page standardController="work__c" extenstions="SearchWorkTest">
<!-- Is it possible to pass argument like 'foo' ? -->
<apex:commandLink value="search!" action="{!searchWorkByName}" />
</apex:page>
You can pass in parameters from a page into a function like this:
<apex:commandLink value="search!" action="{!searchWorkByName}">
<apex:param name="key" value="val"/>
</apex:commandLink>
Obviously, the value of the parameter in this case is fixed. If you want something dynamic (i.e. user types something and that is passed to the function), I'm not 100% sure how you'd do that, but I think it might be possible. However, the solution already posted skins the cat for you, but I thought I'd follow up with an alternative in case it's any use.
No, you cannot pass arguments to actions like that.
1 option is to make this variable a normal form field that user can type text/select from dropdown/whatever - if you'll use same name for a variable in Apex (and make it publicly visible by setters/getters), this will work without problems. Check out my answer at How do I integrate Salesforce with Google Maps? to get started.
Second option - if this search must be somehow done programatically without user having to click anything, if the data for example comes from page itself (i.e. is read in <apex:repeat> tag)... you could make a small helper page & controller and call them as components. There is no problem with passing data to components. Check documentation for <apex:component> and <apex:componentBody>. But I think first answer os most useful for you.
Good luck!