How to join Enum with JavaScript in Spring-Boot application - javascript

I'm a beginer with JavaScript and now I'm facing such problem.
I have an enum
#JsonFormat(shape = Shape.OBJECT)
public enum FinancialEventType {
Income("Income"),
Expense("Expense");
private String code;
private FinancialEventType(String code) {
this.code = code;
}
#JsonValue
public String getCode() {
return this.code;
}
}
and I'd like to pass the enum to my view trough a ModelAttribute(as an object and as an JSON)
#ModelAttribute()
public void addAttributes(Model model) throws JsonProcessingException {
String data1 = new ObjectMapper().writeValueAsString(FinancialEventType.values());
model.addAttribute("data1", data1);
model.addAttribute("eventTypes", FinancialEventType.values());
}
in my view I can get these attributes
<script>
var documentDate = "[[${documentDate}]]";
var eventTypes = "[[${eventTypes}]]";
var data1 = "[[${data1}]]";
console.log("data1: " + data1);
</script>
but the "JSON" looks a bit weird:
data1: ["Income","Expense"]
and when I try the generate a dropdown element via the JavaScript
//Create and append the options
for (var i = 0; i < data1.length; i++) {
var option = document.createElement("option");
option.value = data1[i];
option.text = data1[i];
selectList.appendChild(option);
}
row.appendChild(cell);
the generated list is not what I'm looking for:
thanks for any advice
Witold

Change this:
var data1 = "[[${data1}]]";
for this:
var data1 = [(${data1})];
Using "[[ ]]" in Thymeleaf is equivalent to use th:text, and Thymeleaf is escaping the text (that means, converting the symbol ' in the HTML equivalent &quot). So, use "[( )]" instead, which is equivalent to th:utext.
This will only work with Thymeleaf version 3, not version 2.
Source: https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#inlining

Related

Why are the element of my string list not returning a string when called?

I have these code stumps
Javascript:
vidsrc = #IndexModel.vidFilescs[IndexModel.count].ToString()
function newVid() {
videoplayer.src = vidsrc
}
C#:
public static List<string> vidFilescs = new List<string>();
public static int count = 0;
public static void syncVids()
{
var files = Directory.GetFiles(#"C:\source\repos\htmlscreen\vids");
vidFilescs.Clear();
foreach (var file in files)
{
vidFilescs.Add(file.ToString());
}
}
When i call vidsrc it returns at element as clear text and i get this error in the browser
Uncaught SyntaxError: Unexpected token ':' (at (index):43:15)
I have tried using backticks to call vidsrc in a string.
and as you can see i have tried .ToString() the element.
Given the info you gave me I understand now what you're trying to achieve.
This should work:
var vidsrc = #Html.Raw(Json.Encode(IndexModel.vidFilescs[IndexModel.count]))
Note that IndexModel.count has to have a value, you said count wasn't implemented yet but if you instead use this :
var vidsrc = #Html.Raw(Json.Encode(IndexModel.vidFilescs[0]))
You should get a value back.

How to read string message from ViewBag to Javascript object?

I have this action method which return error message and it did:
var content = responsePost.Content.ReadAsStringAsync().Result;
model = JsonConvert.DeserializeObject<MyAPIResponse>(content);
ViewBag.Message = model.message;
In my Razor view page, I try to read it with the following code:
#{
var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
var userInfoJson = jss.Serialize(ViewBag.Message);
}
<script>
var errors = JSON.parse('#Html.Raw(userInfoJson)');
$(document).ready(function () {
for (var i = 0; i < errors.Count; i++)
{
}
});
</script>
But the output rendered back is:
<script>
var errors = JSON.parse('"[\"Passwords must have at least one non letter or digit character. Passwords must have at least one lowercase (\u0027a\u0027-\u0027z\u0027). Passwords must have at least one uppercase (\u0027A\u0027-\u0027Z\u0027).\"]"');
$(document).ready(function () {
for (var i = 0; i < errors.Count; i++)
{
}
});
</script>
I am using C# MVC Razor for the UI and in my API is Identity for the password policy.
In the controller, just set the object in the bag:
public ActionResult Index()
{
var errors = new[] { "error1", "error2" };
ViewBag.Errors = errors;
return View();
}
Then in view serialize and use it:
<script>
var errors = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.Errors))
errors.forEach(item => { alert(item);});
</script>
Note:
In case you don't have an array in the bag, for example ViewBag.Errors = "error1", then don't use forEach, use alert(errors);
JSON.parse is unnecessary in this case. You are not receiving a string from server, you are rendering the html content and javascripts in the response.

Alfresco datalist send email on very new item creation

I have applied rule on datalist folder like on each item creation, it should drop an email to respective person.
Below is the script for the same:
function main()
{
var site = siteService.getSite("hardik-test");
var dataListsContainer = site.getContainer("datalists");
var dataLists = dataListsContainer.getChildren();
var fullName, manager,joiningDate;
for(var x=0;x<dataLists.length;x++)
{
var dataList = dataLists[x];
var props = dataList.getProperties();
var title = props["cm:title"];
if(title.equals("Employee"))
{
var dataListItems = dataList.getChildren();
for (var y = 0; y < dataListItems.length; y++)
{
var dataListItem = dataListItems[dataListItems.length-1];
var dataListItemProps = dataListItem.getProperties();
fullName = dataListItemProps["emp:fullName"];
manager = dataListItemProps["emp:manager"];
joiningDate = dataListItemProps["emp:joiningDate"];
}
}
}
// create mail action
var mail = actions.create("mail");
mail.parameters.to = "xyz#xyz.com"; //manager email id should be there
mail.parameters.subject = "Task assigned to you.";
mail.parameters.from = "xyz#xyz.com";
//mail.parameters.template = companyhome.childByNamePath("Data Dictionary/Email Templates/Notify Email Templates/notify_user_email.html.ftl");
mail.parameters.text = "Hi "+manager +"," + "\n A new employee " +fullName +" will be joining our team on "+ joiningDate + "." +
"\n For details, Please click here. \n Regards, \n Administrator" ;
mail.execute(document);
}
script is running every time when we create new item but in the email it's not fetching the latest data we entered.
If we want to use email template, then how can we pass parameter(custom values) to email template?
Want to create link that will redirect to datalist.
This is one of the many times when the Alfresco source can be instructive. If you take a look at the MailActionExecuter class you'll see that it has several parameters defined:
public static final String NAME = "mail";
public static final String PARAM_LOCALE = "locale";
public static final String PARAM_TO = "to";
public static final String PARAM_CC = "cc";
public static final String PARAM_BCC = "bcc";
public static final String PARAM_TO_MANY = "to_many";
public static final String PARAM_SUBJECT = "subject";
public static final String PARAM_SUBJECT_PARAMS = "subjectParams";
public static final String PARAM_TEXT = "text";
public static final String PARAM_HTML = "html";
public static final String PARAM_FROM = "from";
public static final String PARAM_FROM_PERSONAL_NAME = "fromPersonalName";
public static final String PARAM_TEMPLATE = "template";
public static final String PARAM_TEMPLATE_MODEL = "template_model";
public static final String PARAM_IGNORE_SEND_FAILURE = "ignore_send_failure";
public static final String PARAM_SEND_AFTER_COMMIT = "send_after_commit";
One of those is PARAM_TEMPLATE_MODEL which you would set by using "template_model". The "model" in that parameter is what should be catching your eye. It means you can pass in a set of keys and values by using that parameter.
Later, in the source for that class we see where the parameter is read and then used to build the full model that is then passed in to the Freemarker template:
Map<String, Object> suppliedModel = null;
if(ruleAction.getParameterValue(PARAM_TEMPLATE_MODEL) != null)
{
Object m = ruleAction.getParameterValue(PARAM_TEMPLATE_MODEL);
if(m instanceof Map)
{
suppliedModel = (Map<String, Object>)m;
}
else
{
logger.warn("Skipping unsupported email template model parameters of type " + m.getClass().getName() + " : " + m.toString());
}
}
// build the email template model
Map<String, Object> model = createEmailTemplateModel(actionedUponNodeRef, suppliedModel, fromPerson, toRecipients);
So, if you comment in the reference to the template and you pass in an additional parameter to the action, assuming your template makes use of the items you add to the model, you should see those in the resulting email.
Your code would look something like:
var templateModel = {};
templateModel["fullName"] = fullName;
templateModel["manager"] = manager;
templateModel["joiningDate"] = joiningDate;
mail.parameters.template_model = templateModel;

return Tuple to js in view

Tried using c# 7 Tuples like
public (string, bool) ProcessForm([FromBody]Dictionary<string,string> contactFormRequest)
But I get the error "CS1031: Type expected". I guess this isn't supported yet.
Then I tried
public Tuple<string, bool> ProcessForm([FromBody]Dictionary<string,string> contactFormRequest)
{
var message = "test";
var result = true;
var tuple = new Tuple<string, bool>(message, result);
return tuple;
}
This gives no error, but then I cannot pick it up in the view file
function handleResult(data) {
$("#custommessages").html(data.Item1);
}
$2sxc(#Dnn.Module.ModuleID).webApi.post("Form/ProcessForm", {}, newItem, true).then(handleResult);
This outputs nothing.
If I return a simple string from the controller, "data" picks it fine.
How do you pick up the values from a Tuple return?
Why not create a POCO class for serialization:
public class SomeResult
{
public string Message{get;set;}
public bool Result{get;set;}
}
then
public SomeResult ProcessForm([FromBody]Dictionary<string,string> contactFormRequest)
{
var message = "test";
var result = true;
return new SomeResult{Message = message, Result = result};
}
Why not just return a IActionResult?
You can simply write an Anonymous type instead of Tuple!
Named Types may take up some useless spaces (As I thinks that...)
Try This:
public IActionResult ProcessForm([FromBody]Dictionary<string,string> contactFormRequest)
{
var message = "test";
var result = true;
//This will create an anonymous type! (you can see its named as "a'")
var resultData = new { Message = message, Result = result };
return Json(resultData);
}
Wish it may help you.

JavaScript equivalent of .NET XML Deserialization

I'm looking for a JavaScript library that can deserialize/unmarshal XML (strings or DOM) to JavaScript classes in a way similar to the .NET XmlSerializer's Deserialize method.
The functionality I'm looking for:
Classes are defined as JavaScript constructor functions.
Mapping between nodes and classes/properties is configurable.
Deserialization result consists of instances of these classes.
For example, the following XML:
<root textAttribute='text1' numberAttribute='1' attributeToIgnore1='ignored1' attributeToIgnore2='ignored2'>
<children>
<child>text2</child>
<child>text3</child>
</children>
<childToIgnore>ignored3</childToIgnore>
</root>
used with JavaScript definitions similar to these:
function RootClass() {
this.stringProperty = "";
this.integerProperty = 0;
this.collectionProperty = [];
}
function ChildClass() {
this.stringProperty = "";
}
should produce JavaScript objects similar to the following:
var result = new RootClass();
result.textProperty = "text1";
result.integerProperty = 1;
result.collectionProperty = [];
result.collectionProperty[0] = new ChildClass();
result.collectionProperty[0].textProperty = "text2";
result.collectionProperty[1] = new ChildClass();
result.collectionProperty[1].textProperty = "text3;
An example of .NET (C#) code that does the same would be something like (see this .NET Fiddle for a working example):
public class Program
{
public static void Main()
{
var result = Serializer.Deserialize();
Console.WriteLine("text: {0}", result.StringProperty);
Console.WriteLine("number: {0}", result.IntegerProperty);
Console.WriteLine("enum: {0}", result.EnumProperty);
Console.WriteLine("child[0].Value: {0}", result.CollectionProperty[0].Value);
Console.WriteLine("other#[0]: {0}", result.OtherAttributes[0].InnerText);
Console.WriteLine("other*[0]: {0}", result.OtherElements[0].InnerText);
}
}
public static class Serializer
{
public static RootClass Deserialize()
{
var type = typeof (RootClass);
var serializer = new XmlSerializer(type);
var xmlString = #"
<root textAttribute='text1' numberAttribute='1' enumAttribute='item1' attributeToIgnore1='ignored1' attributeToIgnore2='ignored2'>
<children>
<child>text2</child>
<child>text3</child>
</children>
<childToIgnore>ignored3</childToIgnore>
</root>";
using (var stringReader = new StringReader(xmlString))
{
return serializer.Deserialize(stringReader) as RootClass;
}
}
}
[XmlRoot("root")]
public class RootClass
{
[XmlAttribute("textAttribute")]
public string StringProperty;
[XmlAttribute("numberAttribute")]
public int IntegerProperty;
[XmlAttribute("enumAttribute")]
public Enumeration EnumProperty;
[XmlAnyAttribute]
public XmlAttribute[] OtherAttributes;
[XmlArray("children")]
[XmlArrayItem("child")]
public Collection<ChildClass> CollectionProperty;
[XmlAnyElement]
public XmlElement[] OtherElements;
}
public enum Enumeration
{
[XmlEnum("item1")]
Item1,
[XmlEnum("item2")]
Item2
}
public class ChildClass
{
[XmlText]
public string Value;
}
Jsonix by Alexey Valikov (source, guide) can deserialize XML to JavaScript based on configurable mapping.
I've contributed code to support deserializing custom classes using instance factories. This will hopefully make it into the next release of Jsonix (2.0.11).
var input = "<element1 attribute1='value1' />";
var Class1 = function () {};
Class1.prototype.toString = function () {
return this.Property1;
};
var mapping = {
elementInfos: [{
elementName: "element1",
typeInfo: new Jsonix.Model.ClassInfo({
name: "Element1",
instanceFactory: Class1,
propertyInfos: [
new Jsonix.Model.AttributePropertyInfo({
name: "Property1",
attributeName: "attribute1"
})
]
})
}]
};
var context = new Jsonix.Context([mapping]);
var unmarshaller = context.createUnmarshaller();
var result = unmarshaller.unmarshalString(input).value;
console.log(result.toString()); // logs "value1"
A longer working example on JSFiddle uses XML from question.

Categories

Resources