I would like to display the count of validation errors to my user.
It is to implement a message like "You have X error(s) left" next to the submit button.
Is there a way to do this ?
Edit :
I am using ember-validations 2.0.0-alpha.1 and ember 1.8.0 in the context of a controller (without ember data).
If I try the solution of Sam:
this.get('errors.length') // result is [], an empty array
The errors key holds an object, not an array. Each key of this object refers to a property on your model and points to an array of error messages, so you can do things like this.get('errors.firstName.length').
To find the total number of errors, you'd have to look through each of your model's properties and sum the number of errors for each one.
http://emberjs.jsbin.com/luzesiyeqi/1/
EDIT:
The .length property of the errors object is returning an empty array because of this code: https://github.com/dockyard/ember-validations/blob/master/addon/errors.js. Literally any key you access on the errors object will be initialized to an empty array.
EDIT 2:
Based on what you said in the comments about not wanting to loop through properties, you can do it in an alternative fashion by looking at the model's validators property. Check out this example:
numErrors: function () {
var errorCounts = this.get('model.validators').mapBy('errors.length');
return errorCounts.reduce(function (a, b) { return a + b }, 0);
}.property('model.validators.#each.length')
I've updated the JSBin, too:
http://emberjs.jsbin.com/jucuxodaga/1/edit?html,js,output
If you're using ember-validations, this will be easy: this.errors.length.
Related
Hi I am trying to extract a value from a Netsuite hash inside custom fields, and some others, which typically look like this - `
"custbody_delivery_ticket_number"=>
{
"script_id"=>"custbody_delivery_ticket_number",
"internal_id"=>"2701",
"type"=>"platformCore:DateCustomFieldRef",
"attributes"=> {
"value"=>"123abc"
}
}` and want the value of it inside of attributes.
Have tried many different ways, but one in particular -
delivery_ticket_number: "#{netsuite_sales_orders.custom_field_list.custom_fields.select['custbody_nef_meter_ticket_number']['attributes']['value']}",
throws error for class Enumerator, NoMethodError: undefined method `[]' for #Enumerator:0x00005589ec778730 which indicates may be getting close, but doing something wrong.
If anyone has any idea how to get values from these kind of hashes?
(Am told by the system admin that it is the correct custbody identifier)
Many Thanks
Eventually fixed this, grabbing Netsuite custom fields with a select of script_id by name,and map as below:
delivery_date:netsuite_sales_order.custom_fields_list.custom_fields.select { |field| field.script_id == 'custbody_delivery_date' }.map { |field| field.value }.first
First selecting the script_id by unique name, then mapping to the value. Was able to get any custom field like this, preferable as they can move and might not have the same index if use an index to grab them, fetching an incorrect value. This way ensures getting the correct data even if the item is moved up or down in the custom fields list.
Thanks for everyones help!
I've seen the JSON array questions here and I'm still a little lost, so could use some extra help.
Here's the setup:
My Flow calls a sproc on my DB and that sproc returns this JSON:
{
"ResultSets": {
"Table1": [
{
"OrderID": 9518338,
"BasketID": 9518338,
"RefID": 65178176,
"SiteConfigID": 237
}
]
},
"OutputParameters": {}
}
Then I use a PARSE JSON action to get what looks like the same result, but now I'm told it's parsed and I can call variables.
Issue is when I try to call just, say, SiteConfigID, I get "The output you selected is inside a collection and needs to be looped over to be accessed. This action cannot be inside a foreach."
After some research, I know what's going on here. Table1 is an Array, and I need to tell PowerAutomate to just grab the first record of that array so it knows it's working with just a record instead of a full array. Fair enough. So I spin up a "Return Values to Virtual Power Agents" action just to see my output. I know I'm supposed to use a 'first' expression or a 'get [0] from array expression here, but I can't seem to make them work. Below are what I've tried and the errors I get:
Tried:
first(body('Parse-Sproc')?['Table1/SiteConfigID'])
Got: InvalidTemplate. Unable to process template language expressions in action 'Return_value(s)_to_Power_Virtual_Agents' inputs at line '0' and column '0': 'The template language function 'first' expects its parameter be an array or a string. The provided value is of type 'Null'. Please see https://aka.ms/logicexpressions#first for usage details.'.
Also Tried:
body('Parse-Sproc')?['Table1/SiteconfigID']
which just returns a null valued variable
Finally I tried
outputs('Parse-Sproc')?['Table1']?['value'][0]?['SiteConfigID']
Which STILL gives me a null-valued variable. It's the worst.
In that last expression, I also switched the variable type in the return to pva action to a string instead of a number, no dice.
Also, changed 'outputs' in that expression for 'body' .. also no dice
Here is a screenie of the setup:
To be clear: the end result i'm looking for is for the system to just return "SiteConfigID" as a string or an int so that I can pipe that into a virtual agent.
I believe this is what you need as an expression ...
body('Parse-Sproc')?['ResultSets']['Table1'][0]?['SiteConfigID']
You can see I'm just traversing down to the object and through the array to get the value.
Naturally, I don't have your exact flow but if I use your JSON and load it up into Parse JSON step to get the schema, I am able to get the result. I do get a different schema to you though so will be interesting to see if it directly translates.
How can I show a validation error for a form field outside of a field constructor in Play framework 2? Here is what I tried:
#eventForm.("name").error.message
And I get this error:
value message is not a member of Option[play.api.data.FormError]
I'm confused because in the api docs it says message is a member of FormError. Also this works fine for global errors:
#eventForm.globalError.message
You can get a better grasp of it checking Form's sourcecode here
Form defines an apply method:
def apply(key: String): Field = Field(
this,
key,
constraints.get(key).getOrElse(Nil),
formats.get(key),
errors.collect { case e if e.key == key => e },
data.get(key))
That, as said in the doc, returns any field, even if it doesn't exist. And a Field has an errors member which returns a Seq[FormError]:
So, you could do something like that (for the Seq[FormError]):
eventForm("name").errors.foreach { error =>
<div>#error.message</div>
}
Or (for the Option[FormError])
eventForm("name").error.map { error =>
<div>#error.message</div>
}
Or, you could use Form errors:
def errors(key: String): Seq[FormError] = errors.filter(_.key == key)
And get all errors of a given key. Like this (for the Seq[FormError]):
eventForm.errors("name").foreach { error =>
<div>#error.message</div>
}
Or (for the Option[FormError])
eventForm.error("name").map { error =>
<div>#error.message</div>
}
If you want more details, check the source code. It's well written and well commented.
Cheers!
EDIT:
As biesior commented: to show human readable pretty messages with different languages you have to check how play works I18N out here
To be thorough you're probably going to have to deal with I18N. It's not hard at all to get it all working.
After reading the documentation you may still find yourself a bit consufed. I'll give you a little push. Add a messages file to your conf folder and you can copy its content from here. That way you'll have more control over the default messages. Now, in your view, you should be able to do something like that:
eventForm.errors("name").foreach { error =>
<div>#Messages(error.message, error.args: _*)</div>
}
For instance, if error.message were error.invalid it would show the message previously defined in the conf/messages file Invalid value. args define some arguments that your error message may handle. For instance, if you were handling an error.min, an arg could be the minimum value required. In your message you just have to follow the {n} pattern, where n is the order of your argument.
Of course, you're able to define your own messages like that:
error.futureBirthday=Are you sure you're born in the future? Oowww hay, we got ourselves a time traveler!
And in your controller you could check your form like that (just one line of code to show you the feeling of it)
"year" -> number.verifying("error.furtureBirthday", number <= 2012) // 2012 being the current year
If you want to play around with languages, just follow the documentation.
Cheers, again!
As you said yourself, message is a member of FormError, but you have an Option[FormError]. You could use
eventForm("name").error.map(_.message).getOrElse("")
That gives you the message, if there is an error, and "" if there isn't.
I'm working on a jsPlumb problem. When I try to programatically remove all of an elements connections, I get Uncaught TypeError: Cannot read property 'left' of undefined
I have several "nodes" (html elements) that each have 1 input endpoint (an end point that accepts) and n output endpoints. Each node also has a javascript object behind it. I have a "selected" state in my software. Users can select multiple nodes and the objects are pushed to an array called selected. I have a key listener for the delete key. When the key is pressed it loops through selected nodes, deleting them and removing their endpoints. This works great when there are no connections, but when there are connections I the error.
The output endpoints are attached to child HTML elements of the main node…
There's a lot of code doing lots of stuff, but I'll try to share the relevant parts:
function Node(jsonFromServer){
/* … this is the constructor method… some code omitted*/
this.endpoints = [];
this.endpoints.push(jsPlumb.addEndpoint(this.el.attr("id"),targetEndpoint,{anchor:"TopCenter",uuid: this.el.attr("id") + "TopCenter"}));
this.addConnectionEndpoints();
}
Node.prototype.addConnectionEndPoints = function(){
//omitting code… loops through 'connections' that don't have 'has endpoint' marked….
this.endpoints.push(jsPlumb.addEndpoint(connection['el'].attr("id"),sourceEndpoint,{anchor:"RightMiddle",uuid:connection['el'].attr("id")+"RightMiddle"}));
connection.hasEndPoint = true;
}
So that was the setup. Here's how I delete
when key pressed
If key is delete /* all this stuff works */
loop through selected array (the array of selected Node elements:works)
node.el.hide(250).remove();
loop through node's endpoints array
//endpoint is the correct object... proved with console.log
//the following line is the error
jsPlumb.deleteEndpoint(endpoint);
ajax call to server to delete stuff on the backend
Fixed it! When I said node.el.hide(250).remove(); I removed an html element that was required in the delete process. I moved the remove part to the callback of the ajax request, and it works like a charm.
I've used "Google AJAX Transliteration API" and it's going well with me.
http://code.google.com/apis/ajaxlanguage/documentation/referenceTransliteration.html
Currently I've a project that I need all input fields in every page (input & textarea tags) to be transliteratable, while these input fields differs from page to page (dynamic).
As I know, I've to call makeTransliteratable(elementIds, opt_options) method in the API call to define which input fields to make transliteratable, and in my case here I can't predefine those fields manually. Is there a way to achieve this?
Thanks in advance
Rephrasing what you are asking for: you would like to collect together all the inputs on the page which match a certain criteria, and then pass them into an api.
A quick look at the API reference says that makeTransliteratable will accept an array of id strings or an array of elements. Since we don't know the ids of the elements before hand, we shall pass an array of elements.
So, how to get the array of elements?
I'll show you two ways: a hard way and an easy way.
First, to get all of the text areas, we can do that using the document.getElementsByTagName API:
var textareas = document.getElementsByTagName("textarea");
Getting the list of inputs is slightly harder, since we don't want to include checkboxes, radio buttons etc. We can distinguish them by their type attribute, so lets write a quick function to make that distinction:
function selectElementsWithTypeAttribute(elements, type)
{
var results = [];
for (var i = 0; i < elements.length; i++)
{
if (elements[i].getAttribute("type") == type)
{
results.push(elements[i]);
}
}
return results;
}
Now we can use this function to get the inputs, like this:
var inputs = document.getElementsByTagName("input")
var textInputs = selectElementsWithTypeAttribute(textInputs, "text");
Now that we have references to all of the text boxes, we can concatenate them into one array, and pass that to the api:
var allTextBoxes = [].concat(textareas).concat(textInputs);
makeTransliteratable(allTextBoxes, /* options here */);
So, this should all work, but we can make it easier with judicious use of library methods. If you were to download jQuery (google it), then you could write this more compact code instead:
var allTextBoxes = $("input[type='text'], textarea").toArray();
makeTransliteratable(allTextBoxes, /* options here */);
This uses a CSS selector to find all of the inputs with a type attribute of "text", and all textareas. There is a handy toArray method which puts all of the inputs into an array, ready to pass to makeTransliteratable.
I hope this helped,
Douglas