Hello,
I am a little be lost with my problem so I hope you can help me to
solve it ... :)
I want to create my own validation plugin by combining it with the
define plugin. Also it should be possible to show the errors easily in
the stache template. At the bottom of my post you will find the source
code (in a more simple version as I want to use it in the future).
It should be possible to write your own validation function into
the define object of the attribute. The validation function will be
called automatically everytime you change the attribute and you can
show it on your template.
My problem is that the global helper which I wrote is called only
one time. I hoped the helper will be called everytime the error list changes.
The helper needs 2 Parameters:
First parameter the map
Second parameter the attribute name
So it should be possible to show the errors or (if there are any
errors) something positive
- {{#verror mymap "attributename"}}
- /* SHOW ERRORS */
- {{else}}
- /* EVERYTHING IS OK */
- {{/verror}}
If the attribute doesn't make any errors at the beginning it
shows the second part. When I change the attribute which runs into a
validation error it should changes and show the first part.
When I execute the sourcecode it show the second part even after
changing the attribute.
I hope you can help me :-/
Thank you in advanced and I wish you all nice holidays ;)
l.
Here is the code:
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <script src="../steal/steal.js"></script>
- <script type="text/javascript">
- steal(
- 'can/view/stache',
- 'can/map',
- 'can/list',
- 'can/map/define',
- function() {
- can.stache.registerHelper("verror", function(data, prop, options) {
- var obj = data;
- // data is a mixin(?) function. I have to execute the function to get the map so I can use it.
- if(typeof obj == "function") {
- obj = obj();
- }
- else {
- return arguments[arguments-1].inverse(this);
- }
- // write the error list, which will be filled by the validate function, into errorlist
- errorlist = obj.attr("errorlist").attr(prop);
- // if the list has items it is positive.
- if(errorlist.length > 0) {
- return options.fn(errorlist);
- }
- return options.inverse(this);
- });
- can.extend(can.Map.prototype, {
- // my validation function
- validate: function(prop) {
- // try to get the errorlist from the map.
- var errorlist = this.attr("errorlist");
- // if there is no errorlist (because it is the first call) create a new map
- if(errorlist === undefined) {
- errorlist = new can.Map();
- this.attr("errorlist", errorlist);
- }
- // try to get the errorlist for the attribute "prop"
- var proplist = errorlist.attr(prop);
- // if there is no list in errorlist (= first call for this prop) create new list
- if (proplist === undefined) {
- proplist = new can.List();
- errorlist.attr(prop, proplist);
- }
- // if there is already a list with error they will be erased.
- else if(proplist.length > 0) {
- proplist.splice(0,proplist.length);
- }
- if(typeof this.define[prop].validate == "function") {
- var vallist = new can.List();
- // call the validationplugin and write the erros into the temp. list "vallist"
- this.define[prop].validate.call(this, vallist);
- // write every item from vallist into the errorlist
- for(var i = 0; i < vallist.length; ++i) {
- var item = new can.Map();
- item.attr("errorcode", vallist[i]);
- item.attr("prop", prop);
- item.attr("other", "stuff");
- proplist.push(item);
- }
- }
- }
- });
- mappro = can.Map.prototype;
- var odset = mappro.__set;
- mappro.__set = function (prop, value, current, success, error) {
- odset.call(this, prop, value, current, success, error);
- // Only if the map has a define map the validation will be executed.
- if(this.define && this.define[prop] && this.define[prop].validate) {
- this.validate.call(this, prop);
- }
- return this;
- };
- var ExampleMap = can.Map.extend({
- define: {
- valStr: {
- type: "string",
- value: "",
- // my validation function for the attribute
- validate: function(errors) {
- if(this.valStr == "foo") {
- errors.push("bar");
- }
- }
- },
- valNum: {
- type: "number",
- value: 10,
- validate: function(errors) {
- if(this.valNum > 100) {
- errors.push("valNumTooHigh");
- }
- else if(this.valNum < 0) {
- errors.push("valNumTooSmall");
- }
- if(this.valNum % 2 == 1) {
- errors.push("ohNo");
- }
- }
- }
- }
- });
- mymap = new ExampleMap({
- valStr: "asdf"
- ,valNum: 123
- });
- var data = new can.Map({
- mymap: mymap,
- foo: "bar"
- });
- $("#div").html(can.view("tpl",data));
- }
- );
- </script>
-
-
- <script type="text/stache" id="tpl">
- <div style="padding-bottom:50px">
- <div>foo: {{foo}}</div>
- <div>mymap: valStr:{{mymap.valStr}} / valNum: {{mymap.valNum}}</div>
- </div>
- <div> <strong>error list (valStr):</strong></div>
- <div>
- {{#verror mymap "valStr"}}
- {{#each .}}
- <div style="color:red"> errorcode: {{errorcode}}</div>
- {{/each}}
- {{else}}
- <div style="color:green">everything is fine</div>
- {{/verror}}
- </div>
- <div> <strong>error list (valNum):</strong></div>
- <div>
- {{#verror mymap "valNum"}}
- {{#each .}}
- <div style="color:red"> errorcode: {{errorcode}}</div>
- {{/each}}
- {{else}}
- <div style="color:green">everything is fine</div>
- {{/verror}}
- </div>
- </script>
- </head>
- <body >
- <div>
- <div id="div"></div>
- </div>
- </body>
- </html>