Orchard Workflows - keep format of text in textarea - orchardcms

I have a workflow that sends an email when a form is submitted that contains a textarea.
My problem is that the formatting of the content entered into the textarea is lost (e.g. carriage returns / paragraphs) when the email is sent.
Is there a way to maintain the content exactly as the user entered it? At present I am using this to output the content in the Email activity:
<p>Message:<br/>
{Request.Form:Message}</p>
It is running Orchard 1.10.2. Any help much appreciated!

EDIT
If you use dynamic forms this syntax will work:
FormSubmission.Field:Message.LineEncode
If it is your own form I'm afraid it looks like it is a bug in Orchard where the chained value of a Request.Form is actually retrieving the named query string parameter instead. To sort this you will have to edit this file of the source: Orchard.Tokens.Providers.RequestTokens.
Add a new method:
private static Tuple<string, string> FilterChainParam(string token, string tokenType) {
if(token.StartsWith(tokenType, StringComparison.OrdinalIgnoreCase)) {
return FilterChainParam(token);
}
return null;
}
Then replace this line in the Evaluate method:
.Chain(FilterChainParam, "Text", (token, request) => request.QueryString.Get(token))
with these lines:
.Chain((token) => FilterChainParam(token, "QueryString"), "Text", (token, request) => request.QueryString.Get(token))
.Chain((token) => FilterChainParam(token, "Form"), "Text", (token, request) => request.Form.Get(token))
.Chain((token) => FilterChainParam(token, "Route"), "Text", (token, request) => GetRouteValue(token, request))
Not particularly pretty but it works. You can now use as below (note the parentheses around your form field)
ORIGINAL
Your form will come through with just new lines (\n) which the email client will ignore. You'll need to replace them with line breaks. Fortunately someone thought of this and there is a token for that in Orchard: LineEncode. Change your email activity to:
<p>Message:<br/>
{Request.Form:(Message).LineEncode}</p>

Related

Mutator runs on update but cell data unchanged

I want to create a new field reservationAction and put into my table as a column Reservation defined as:
{title: "Reservation", field: "reservationAction", mutator: reservationMutator},
with reservationMutator as:
var reservationMutator = function(value, data, type, params, component) {
console.log(data);
if (!data.checkoutable) return null;
if (data.is_reserved) {
return "Free";
}
return "Get";
}
is_reserved and checkoutable are pre-existing fields of my data.
When the page initially loads, and table is created using ajax, the cell shows the correct string for Reservation. When is_reserved is changed server-side, I call table.updateOrAddData([newData]) (as part of websocket event-handler).
The problem:
When table.updateOrAddData([newData]) run, I can see the custom mutator get triggered
and from the console.log() line, see that the reservationAction is correctly set in the log. But the table itself is showing the old value. Other (non-mutating) columns are updated on the table as expected. Am I missing something or is this a bug?
If instead I use table.replaceData(), then both console, and table show correct value. But I would want to avoid doing this on each websocket event for performance reasons.
Version: I've tried all 5+.
Any help would be appreciated!
jsfiddle
Don't know if this is a workaround or how I'm actually supposed to do it in the first place but, doing row.reformat() seems to do what I expect. Oh well.
table.updateOrAddData([row_obj])
.then(function(rows){
rows.forEach(row => {
row.reformat();
});
});

How to add a field to a Content-Type in OrchardCoreCMS?

Using code, I am trying to create a "Widget" Content-Type called FeaturedProperties with an editable field called MaxVisibleField. I want the MaxVisibleField field to show up under the Fields section when editing the content-type.
I used migration to create a new Contact-Part called MaxPropertiesToShow and created a field called MaxVisibleField for the MaxPropertiesToShow part.
I am expecting the MaxVisibleField field to show up when the “Widget” is edited in the admin panel. When I edit the FeaturedProperties content-type, I see no fields listed. However, I do see the part.
What else do I need to do to make my field MaxVisibleField show up when my Widget is being edited?
Here is my migration code
public int Create()
{
_contentDefinitionManager.AlterPartDefinition("MaxPropertiesToShow", (part) =>
{
part.WithField("MaxVisibleField", c =>
{
c.OfType(nameof(NumericField))
.WithDisplayName("Max Properties To Show")
.WithDescription("The app with display up to this many properties")
.WithSettings(new NumericFieldSettings()
{
Required = true,
Maximum = 50,
DefaultValue = "8",
});
});
});
_contentDefinitionManager.AlterTypeDefinition("FeaturedProperties", (type) =>
{
type.Stereotype("Widget")
.Creatable(false)
.Listable(false)
.Versionable(false)
.WithPart(nameof(FeaturedPropertyPart));
});
return 1;
}
Here is a screenshot of what I am seeing
Also, in the Widget-FeaturedProperties.cshtml view, how can I render the title in a place I want it to show up instead of the standard position the app displays it in?

BeginForm and AttributeRouting [duplicate]

I'm creating a form for a DropDown like this:
#{
Html.BeginForm("View", "Stations", FormMethod.Get);
}
#Html.DropDownList("id", new SelectList(ViewBag.Stations, "Id", "Name"), new { onchange = "this.form.submit();" })
#{
Html.EndForm();
}
If I choose a value from my dropdown I get redirected to the correct controller but the URL is not as I would like to have it:
/Stations/View?id=f2cecc62-7c8c-498d-b6b6-60d48a862c1c
What I want is:
/Stations/View/f2cecc62-7c8c-498d-b6b6-60d48a862c1c
So how do I get the id= querystring parameter replaced by the more simple URL Scheme I want?
A form with FormMethod.Get will always post back the values of its form controls as query string values. A browser cannot generate a url based on your route configurations because they are server side code.
If you really wanted to generate /Stations/View/f2cecc62-7c8c-498d-b6b6-60d48a862c1c, then you could use javascript/jquery to build your own url and redirect
#using (Html.BeginForm("View", "Stations", FormMethod.Get))
{
#Html.DropDownList("id", new SelectList(ViewBag.Stations, "Id", "Name"))
}
var baseUrl = '#Url.Action("View", "Stations")';
$('#id').change(function() {
location.href = baseUrl + '/' $(this).val();
});
Side note: Submitting on the .change() event is not expected behavior and is confusing to a user. Recommend you add a button to let the user make their selection, check it and then submit the form (handle the button's .click() event rather that the dropdownlist's .change() event)
Remove "id"
from
#Html.DropDownList("id", new SelectList(ViewBag.Stations, "Id", "Name"), new { onchange = "this.form.submit();" })

Task with Save button throws validation errors

I have a webMethods CAF task that has a big form with a save button and a submit button. Many elements on the form have validation. The user needs to be able to hit Save and have the form submitted to the back end model so it can be saved as task data, without firing validation. Hitting Submit should fire validation.
How can I configure the page to do this. It's such a normal requirement, and I'm stuck!
It's not much fun.
Give your Save button a nice ID. Say, saveButton
Create a getter in your Java code that returns a boolean. Inside it, return true if the button's ID is one of the submitted fields, otherwise false:
private boolean validationRequired() {
return mapValueEndsWith((Map<String, String>)getRequestParam(),
new String[] {
"saveButton", // Your save button
"anotherButton", // Perhaps another button also shouldn't validate
"myForm:aThirdButton" // perhaps you want to be specific to a form
});
}
In every field that should be required, except on Save, bind the Validation->required attribute to your validationRequired getter.
That's it! Very tedious with a lot of fields on the screen, but it works.
P.s. what's mapValueEndswith? Just a utility; removed whitespace for compactness' sake:
private boolean mapValueEndsWith(Map<String, String> haystack, String[] needles) {
for(String needle : needles) if(mapValueEndsWith(haystack, needle)) return true;
return false;
}
private boolean mapValueEndsWith(Map<String, String> haystack, String needle) {
for(String value : haystack.values()) if(value.endsWith(needle)) return true;
return false;
}
As I see the approach provided, works only if the form contains only string type fields. If there are any other data types like integer, float, data-time are mapped to UI fields and conversion is used then this might fail if wrong data is entered in those fields.

use drupal hook_nodeapi

i have a page tweety which contains a single form where a user enters a word in a textbox and in on pressing search the tweets corresponding to that word are displayed.
I want to use hook_nodeapi to add these tweets but i want those things only on a specific url not all the page(or any node type).
I ll use hook_menu to make that page and display the form for the search. What should i do after that. I knw the twiiter api to fetch the tweets so that is not a issue.
I think what you're attempting to do is have the tweets load on a predetermined page by passing the posted information to the page, is that correct?
There's a couple ways I think you could accomplish this - easiest, and not requiring any complex ahah scripting would be to take the word they enter and generate a path which you could then use to make the page in question.
Make a menu Item:
function mymodule_menu() {
$items = array();
$items['mymodule/tweets/%'] = array(
'title' => t('Tweets about' . check_plain(array(2))),
'page callback' => 'mymodule_tweet_display',
'page arguments' => array(2) // This is the 3rd argument in the path, the %
);
}
In your form, you'll need to send the user to this path so add to your hook_submit function:
$tweet_topic = $form_state['values']['your-field-name-here'];
drupal_goto('mymodule/tweets/' . $tweet_topic);
Now add your page module, this is where you can use the twitter api:
function mymodule_tweet_display($tweet_topic) {
$tweet_topic = check_plain($tweet_topic);
// Use this variable in your Twitter API call
// ...
// Make sure you assign your display content to the page by returning a variable
return $page;
}

Resources