JQuery plugin not working on codepen, works great elsewhere - javascript

I have a plugin that I just wrote, which is so far acting just I had hoped while developing. I attempted to take this code out of my scripts directory and post it on Codepen.io. I get a script error when running it there, the error is cannot read 'Action' of undefined. It gets instantiated by a click event which passes an event. Both using jQuery 2.1. Anyone know whats happening here?
Heres the codepen:
http://codepen.io/nicholasabrams/pen/uJKrL
// $ DOC
$.fn.dataValidate = function(event, userSettings) {
"use strict";
event.preventDefault();
var api = {
// Script definition defaults defined in object below
notNull: {
errorText: 'This field is required',
symbol: false,
Action: function(dataToCheck, instance) {
if (dataToCheck === '' || dataToCheck === null || dataToCheck === 'undefined' || dataToCheck.length === 0 ) {
// if true return true to caller
alert('null');
// Retrieve errorText
// Wrap in error template
this.errorForNotNull = new api.ErrorInjector(instance);
return false;
}
else {
return true;
}
}
},
isNaN: {
errorText: 'Numbers not allowed here',
symbol: false,
Action: function(dataToCheck, instance) {
api.notNull.Action(dataToCheck, instance); /* Reuse the notNull method as a screening service before entering into the method specific filtering (assuming null fields would be inappropriate in any types of check) */
if (isNaN(dataToCheck)){ // Check if the not null field is also non a number
return true;
}
else {
this.errorForIsNan = new api.ErrorInjector(instance);
return false;
}
}
},
isNum: {
errorText: 'Please enter a number',
symbol: false,
Action: function(dataToCheck, instance) {
api.notNull.Action(dataToCheck, instance);
if (!isNaN(dataToCheck)){ // Check if the not null field is also non a number
return true;
}
else {
this.errorForIsNan = new api.ErrorInjector(instance);
return false;
}
}
},
isEmail: {
errorText: 'Please enter a valid email address',
symbol: false,
Action: function(dataToCheck, instance) {
api.notNull.Action(dataToCheck, instance);
var checkEmailRegEx = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (checkEmailRegEx.test(dataToCheck)){
}
else {
this.errorForIsEmail = new api.ErrorInjector(instance);
}
}
},
isPw: {
errorText: 'Please enter a password',
symbol: false,
Action: function(dataToCheck, instance) {
api.notNull.Action(dataToCheck, instance);
console.log(dataToCheck);
if (dataToCheck.length > 4){
var isPwRegEx = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/;
if(isPwRegEx.test(dataToCheck)){
// Multiple pw checkpoints here
// At least one upper case English letter
// At least one lower case English letter
// At least one digit
// At least one special character
return false;
}
else {
this.errorForIsPw = new api.ErrorInjector(instance);
return true;
}
}
} // End length check for isPw
},
isPhoneNumber: {
errorText: 'Please enter a valid phone number',
symbol: false,
Action: function(dataToCheck, instance) {
api.notNull.Action(dataToCheck, instance);
this.errorForIsPhoneNumber = new api.ErrorInjector(instance);
}
},
isUsername: {
errorText: 'Please enter a valid username',
symbol: false,
Action: function(dataToCheck, instance) {
api.notNull.Action(dataToCheck, instance);
var checkUsernameRegEx = /^[a-zA-Z0-9.\-_$#*!]{3,30}$/;
if (checkUsernameRegEx.test(dataToCheck)){
alert('valid username');
}
else {
this.errorForIsEmail = new api.ErrorInjector(instance);
}
}
},
isNamePart: {
errorText: 'Please enter a valid name',
symbol: false,
Action: function(dataToCheck, instance) {
api.notNull.Action(dataToCheck, instance);
var checkNamePartRegEx = /^[a-zA-Z ]+$/;
if (checkNamePartRegEx.test(dataToCheck)){
alert('valid name part');
}
else {
this.errorForIsEmail = new api.ErrorInjector(instance);
}
}
},
// New method would be added here
errorOutput: 'validated',
targets: ['[data-validate="notNull"]', '[data-validate="isNaN"]',
'[data-validate="isNum"]', '[data-validate="isEmail"]', '[data-validate="isPw"]', '[data-validate="isPhoneNumber"]', '[data-validate="isUsername"]','[data-validate="isNamePart"]'],
// Target selectors, can be modified on initialization to that of your liking, as well as have new ones added. Add a new selector target at the end of the array above
placeholder: {
// Template shared by each validation output error
template: {
defaultPlaceholderContainerStyle: 'position: relative;background:#ccc;',
defaultPlaceholderStyle: 'position: absolute;left:0;top:0;width:100%;line-height:26px;height:100%;',
// The above styles may be easily detached by simply tranfering the above CSS to a style rule matching the errorOutput class outlined above in this same object, or set on instantiation
},
},
ErrorInjector: function(instance) {
var errorNs = instance.data('validate');
var error = '<div data-validate="output" class="' + api.errorOutput + '">' + api[errorNs].errorText + '<\/div>';
instance.wrap('<div data-validate="output_container" class="' + api.errorOutput + '_container"><\/div>');
instance.before(error);
},
acceptedTypes : ['input[type="text"]','input[type="email"]','input[type="password"]','input[type="checkbox"]','input[type="radio"]','input[type="tel"]'],
results: {} // NS for all validation results and debugging info (see below)
};
// Merge the caller sent options object with the defaults. Any options set in on init from the caller will overwrite the default/internal settings
this._overrideApiWithUserSettings = (function() {
$.extend(true, api, userSettings);
})();
var targetsAll = api.targets;
// Private utility for removing the validationOutput errors from the DOM
this._removeThisErrorFocusThisInput = function() {
var activeOutputPlaceholder = $(this);
activeOutputPlaceholder.unwrap();
activeOutputPlaceholder.remove();
$.each(api.acceptedTypes, function(){
var eachTypeInAcceptedTypes = this;
activeOutputPlaceholder.find(eachTypeInAcceptedTypes).focus();
});
$('body').unbind('click', '.' + api.errorOutput);
};
$('body').on('click', '.' + api.errorOutput, this._removeThisErrorFocusThisInput);
// Fire each module off conditionally, based on the presence of the targets set on init
this._instantiateByDataValues = (function() { // The core of the script, carefully loadings only each modular bit of functionality by its request in the DOM via data-validate=""
$.each(targetsAll, function( /*iteration*/ ) { /* Iterate through all of the selectors in the targets array, doing the following with each instance of them found in the DOM, passing iteration for debugging purposed only */
var selectorTargetFromArray = $(this);
$.each(selectorTargetFromArray, function() {
var instance = $(this),
thisFnFromDomDataAttrNS = instance.data('validate');
if (instance.length) { // If any of the selectors in the targets array are found to be in the the DOM on init
// Fire the constructor on the element with the data-validate="thisMethod", while passing its value to its action (all method modules and method specific functionality is named based on the selector that is responsible for its instantiation)
this.executeActionByCallerName = new api[thisFnFromDomDataAttrNS].Action(instance.val(), instance);
//! This fires off the action of the module itself off by the name of the value in the data-validate="functionNameHere"
}
else {
this._createNoRunLog = api.results[this] = false; // Store refs to any built in methods not used for your debugging pleasure, under the name it is called by and on
console.log(api.results);
}
});
});
})();
return this;
}; // End preValidation module

Works fine on JSFiddle.. http://jsfiddle.net/exsfabxr/ I guess I can rule out my code as the issue here? Seems that this is an internal Codepen.io issue?
$(function(){ alert('same code as above, i just wrote this because of stackoverflows "smart" validation'); window.location.href = 'http://jsfiddle.net/exsfabxr/'; });

Related

Copy value of date field in YouTrack

I want to copy the value from issues in one project to issues in another that depend on it.
That is what I have:
var entities = require('#jetbrains/youtrack-scripting-api/entities');
var workflow = require('#jetbrains/youtrack-scripting-api/workflow');
exports.rule = entities.Issue.onChange({
// TODO: give the rule a human-readable title
title: 'Date-propagation',
guard: function(ctx) {
var links = ctx.issue.links['depends on'];
return ctx.issue.isChanged("Date") || !links.added.isEmpty() || !links.removed.isEmpty();
},
action: function(ctx) {
var issue = ctx.issue;
var links = issue.links['depends on'];
function updateIssue(normalIssue){
normalIssue.fields.DueDate = issue.fields.Date.value;
}
function checkList(list){
if(list.isNotEmpty())list.forEach(function(normalIssue){updateIssue(normalIssue);}) ;
}
//checkList(links.removed);
checkList(links);
// TODO: specify what to do when a change is applied to an issue
},
requirements: {
Date: {
type: entities.Field.dateType,
},
Depend: {
type: entities.IssueLinkPrototype,
outward: 'is required for',
inward: "depends on"
}
}
});
The problem is in this line:
normalIssue.fields.DueDate = issue.fields.Date;
How should it be done?
Most probably, you do not have a 'DueDate' field on your instance (as the default field is called 'Due Date'). If so, your code line should look like this:
normalIssue.fields['Due Date'] = issue.fields.Date;

Unreliable behaviour in Node.js

I have a Node.js application that, upon initialisation, reads two tables from an SQL database and reconstructs their relationship in memory. They're used for synchronously looking up data that changes (very) infrequently.
Problem: Sometimes I can't access the data, even though the application reports successfully loading it.
Code:
constants.js
module.exports = {
ready: function () { return false; }
};
var log = sysLog('core', 'constants')
, Geo = require('../models/geo.js');
var _ready = false
, _countries = []
, _carriers = [];
function reload() {
_ready = false;
var index = Object.create(null);
return Geo.Country.find().map(function (country) {
var obj = country.toPlainObject()
, id = obj.id;
delete obj.id;
index[id] = obj;
return Object.freeze(obj);
}).then(function (countries) {
log.debug('Loaded ' + countries.length + ' countries');
_countries = countries;
return Geo.Carrier.Descriptor.find().map(function (carrier) {
var obj = carrier.toPlainObject();
if (obj.country) {
obj.country = index[obj.country];
}
return Object.freeze(obj);
}).then(function (carriers) {
log.debug('Loaded ' + carriers.length + ' carriers');
_carriers = carriers;
});
}).finally(function () {
_ready = true;
});
}
reload().catch(function (err) {
log.crit({ message: 'Could not load constants', reason: err });
process.exit(-42);
}).done();
module.exports = {
reload : reload,
ready : function () { return _ready; },
countries : function () { return _countries; },
carriers : function () { return _carriers; }
};
utils.js
var log = sysLog('core', 'utils')
, constants = require('./constants');
module.exports = {
getCountryByISO: function(iso) {
if (!iso) {
return;
}
if ('string' != typeof iso) {
throw new Error('getCountryByISO requires a string');
}
if (!constants.ready()) {
throw new UnavailableError('Try again in a few seconds');
}
switch (iso.length) {
case 2:
return _.findWhere(constants.countries(), { 'iso2' : iso.toUpperCase() });
case 3:
return _.findWhere(constants.countries(), { 'iso3' : iso.toUpperCase() });
default:
throw new Error('getCountryByISO requires a 2 or 3 letter ISO code');
}
},
getCarrierByCode: function(code) {
if (!code) {
return;
}
if ('string' != typeof code) {
throw new Error('getCarrierByCode requires a string');
}
if (!constants.ready()) {
throw new UnavailableError('Try again in a few seconds');
}
return _.findWhere(constants.carriers(), { 'code' : code });
},
getCarrierByHandle: function(handle) {
if (!handle) {
return;
}
if ('string' != typeof handle) {
throw new Error('getCarrierByHandle requires a string');
}
if (!constants.ready()) {
throw new UnavailableError('Try again in a few seconds');
}
return _.findWhere(constants.carriers(), { 'handle' : handle });
}
};
Use case
if (data.handle) {
carrier = utils.getCarrierByHandle(data.handle);
if (_.isEmpty(carrier)) {
throw new InternalError('Unknown carrier', { handle: data.handle });
}
}
What's going on: All errors are logged; as soon as I see an error (i.e. "Unknown carrier") in the logs, I check the SQL database to see if it should've been recognised. That has always been the case so far, so I check the debug log to see if data was loaded. I always see "Loaded X countries" and "Loaded Y carriers" with correct values and no sign of "Could not load constants" or any other kind of trouble.
This happens around 10% of the time I start the application and the problem persists (i.e. didn't seem to go away after 12+ hours) and seems to occur regardless of input, leading me to think that the data isn't referenced correctly.
Questions:
Is there something wrong in constants.js or am I doing something very obviously wrong? I've tried setting it up for cyclical loading (even though I am not aware of that happening in this case).
Why can't I (sometimes) access my data?
What can I do to figure out what's wrong?
Is there any way I can work around this? Is there anything else I could to achieve the desired behaviour? Hard-coding the data in constants.js is excluded.
Additional information:
constants.reload() is never actually called from outside of constants.js.
constants.js is required only in utils.js.
utils.js is required in app.js (application entry); all files required before it do not require it.
SQL access is done through an in-house library built on top of knex.js and bluebird; so far it's been very stable.
Versions:
Node.js v0.10.33
underscore 1.7.0
bluebird 2.3.11
knex 0.6.22
}).finally(function () {
_ready = true;
});
Code in a finally will always get called, regardless of if an error was thrown up the promise chain. Additionally, your reload().catch(/* ... */) clause will never be reached, because finally swallows the error.
Geo.Country.find() or Geo.Carrier.Descriptor.find() could throw an error, and _ready would still be set to true, and the problem of your countries and carriers not being set would persist.
This problem would not have occurred if you had designed your system without a ready call, as I described in my previous post. Hopefully this informs you that the issue here is really beyond finally swallowing a catch. The real issue is relying on side-effects; the modification of free variables results in brittle systems, especially when asynchrony is involved. I highly recommend against it.
Try this
var log = sysLog('core', 'constants');
var Geo = require('../models/geo.js');
var index;
var _countries;
var _carriers;
function reload() {
index = Object.create(null);
_countries = Geo.Country.find().map(function (country) {
var obj = country.toPlainObject();
var id = obj.id;
delete obj.id;
index[id] = obj;
return Object.freeze(obj);
});
_carriers = _countries.then(function(countries) {
return Geo.Carrier.Descriptor.find().map(function (carrier) {
var obj = carrier.toPlainObject();
if (obj.country) {
obj.country = index[obj.country];
}
return Object.freeze(obj);
});
});
return _carriers;
}
reload().done();
module.exports = {
reload : reload,
countries : function () { return _countries; },
carriers : function () { return _carriers; }
};
constants.reload() is never actually called from outside of
constants.js.
That's your issue. constants.reload() reads from a database, which is an aysnchronous process. Node's require() is a synchronous process. At the time constants.js is required in utils.js and the module.exports value is returned, your database query is still running. And at whatever point in time that app.js reaches the point where it calls a method from the utils module, that query could still be running, resulting in the error.
You could say that requiring utils.js has the side-effect of requiring constants.js, which has the side-effect of executing a database query, which has the side-effect of concurrently modifying the free variables _countries and _carriers.
Initialize _countries and _carriers as unresolved promises. Have reload() resolve them. Make the utils.js api async.
promises.js:
// ...
var Promise = require('bluebird');
var countriesResolve
, carriersResolve;
var _ready = false
, _countries = new Promise(function (resolve) {
countriesResolve = resolve;
})
, _carriers = new Promise(function (resolve) {
carriersResolve = resolve;
});
function reload() {
_ready = false;
var index = Object.create(null);
return Geo.Country.find().map(function (country) {
// ...
}).then(function (countries) {
log.debug('Loaded ' + countries.length + ' countries');
countriesResolve(countries);
return Geo.Carrier.Descriptor.find().map(function (carrier) {
// ...
}).then(function (carriers) {
log.debug('Loaded ' + carriers.length + ' carriers');
carriersResolve(carriers);
});
}).finally(function () {
_ready = true;
});
}
reload().catch(function (err) {
log.crit({ message: 'Could not load constants', reason: err });
process.exit(-42);
}).done();
module.exports = {
reload : reload,
ready : function () { return _ready; },
countries : function () { return _countries; },
carriers : function () { return _carriers; }
};
utils.js
getCarrierByHandle: function(handle) {
// ...
return constants.carriers().then(function (carriers) {
return _.findWhere(carriers, { 'handle' : handle });
});
}
Use case:
utils.getCarrierByHandle(data.handle).then(function (carrier) {
if (_.isEmpty(carrier)) {
throw new InternalError('Unknown carrier', { handle: data.handle });
}
}).then(function () {
// ... next step in application logic
});
This design will also eliminate the need for a ready method.
Alternatively, you could call constants.reload() on initialization and hang all possibly-dependent operations until it completes. This approach would also obsolete the ready method.
What can I do to figure out what's wrong?
You could have analyzed your logs and observed that "Loaded X countries" and "Loaded Y carriers" were sometimes written after "Unknown carrier", helping you realize that the success of utils.getCarrierByHandle() was a race condition.

ExtJS Ajax problems for grid panel

I have a grid Panel in my code as:
Ext.create('Ext.grid.Panel', {
id : 'frPanel-' + interfaceId,
store : frStore,
columns : [
{
text : 'Sequence',
dataIndex : 'ruleId',
menuDisabled : true
},
{
text : 'Source',
dataIndex : 'source',
renderer : function(value, metaData) {
var newValue = convertObjValue(value);
if (newValue.match(/[-]+/i)) {
metaData.tdAttr = 'data-qtip="'
+ networkStore(value) + '"';
}
return newValue;
}
},
// paging bar at the bottom
dockedItems : [ {
xtype : 'pagingtoolbar',
store : frStore, // same store GridPanel is using
dock : 'bottom',
displayInfo : true
} ],
height : 300,
width : '100%',
forceFit : true,
renderTo : 'frContainer-' + interfaceId
});
And these are the helper function i have:
// To get the value after 2nd colon for object and object-group
function convertObjValue(value) {
var result;
var exp = /.*?:.*?:(.*)/i;
var newValue = value;
if ((result = exp.exec(value)) != null) {
if (result.index === exp.lastIndex) {
exp.lastIndex++;
}
newValue = result[1];
}
return newValue;
}
The store:
function networkStore(value) {
//var store = Ext.create('Ext.data.Store', {
var store = new Ext.data.Store({
model : 'networkModel',
autoLoad : {
timeout : 60000
},
proxy : {
type : 'ajax',
url : networkObjsURL + "&" + Ext.urlEncode({
'peId' : value
}),
reader : {
type : 'json',
idProperty : 'objValue'
},
}
});
var hoverOutput = "";
if(store.data.length > 0){
store.data.items.forEach(function(item) {
hoverOutput += item.data.objectValue + "</br>";
});
}
console.log(hoverOutput);
return hoverOutput;
and last but not the least is the model:
Ext.define('networkModel', {
extend : 'Ext.data.Model',
fields : [ {
name : 'objectValue'
} ]
});
Now comes the issue. The problem is when i dont place the breakpoint in the browser in store, the values wont show up in qtip. Im guessing thats because of the grid panel not waiting for the response back from the store after ajax response. Can someone help me figure out a workaround for this situation?
Thanks in advance
Have you tried setting
autoLoad:false
and then something like :
store.load({
callback: function(records, operation, success) {
if (success == true) {
//do your stuff
var hoverOutput = "";
if(store.data.length > 0){
store.data.items.forEach(function(item) {
hoverOutput += item.data.objectValue + "</br>";
});
}
console.log(hoverOutput);
return hoverOutput;
} else {
// the store didn't load, deal with it
}
}
// scope: this,
});
Since your breakpoint allows you to see your data, im thinking you are right in assuming it's a delay issue. Since Ext is asynchronous, it wont wait for the ajax call to be finished before continuing it's processing. A callback will help you manage this as it will be called when ajax returns.
I'm still also fairly new to Ext but at least that's my understanding. Hope it helps, or at least points you in the right way.
Edit because i reminded that sometimes having a return inside the success will make it hard to debug, etc. So you could also try changing your success to call another function and have that function do the processing, just keep the scope in mind.
I asked in comment which version ExtJS you're using but I didn't get response so I assume that you are using ExtJS 5.
Control Flow in your code is strange for me.
Why do you create store in render function indirectly (directly in networkStore) multiple times?
Nevertheless, store is fetching data asynchronous, so you have to wait/callback result (or use Future/Promise API for example). In addition, you should have any necessary data for the grid in frStore store (which you pass to the grid). You can also take advantage of data association in your model or you can create new field in model with convert function and use value of the association/field in render function.
Let me show you one of the approach how to do that (a simple one).
ExtJS doesn't like modifying records inside render function so we prepare a model which has a necessary qtip value.
I assume that you can load data of networkStore earlier (autoload: true) but this is for simplicity and you can change it later, for example using remoteFilter and callbacks.
You don't show definition of frStore and underlying model so I will use FrStore and FrModel as class names.
Ext.define('FrModel', {
extend: 'Ext.data.Model',
// ...
fields: [
// source field
// ...
/** qtip value **/
{
name: 'qtip',
type: 'string',
convert: function (value, record) {
var result = '';
// below code is from your render function with modifications
if (record.get('rendered_source').match(/[-]+/i)) {
result = 'data-qtip="'
+ networkStore(record.get('source')) + '"';
}
return result;
},
depends: ['source', 'rendered_source']
},
/** rendered source **/
{
name: 'rendered_source',
type: 'string',
convert: function (value, record) {
var newValue = convertObjValue(record.get('source'));
return newValue;
},
depends: ['source']
}
]
// ...
}
After that change render function is simple:
// ...
{
text : 'Source',
dataIndex : 'rendered_source', // this will allow users to sort & filter this field by the values which are displayed
renderer : function(value, metaData, record) {
metaData.tdAttr = 'data-qtip="'
+ record.get('qtip') + '"';
}
return value;
}
},
// ...
You can need also a NetworkStore which you could place in seperate file: (I prefer proxy/schema in model but I've used your code)
Ext.create('Ext.data.Store', { // using Ext.create is better
model : 'networkModel',
storeId: 'networkStore', // registering store in Ext.data.StoreManager in order to get later this store by Ext.getStore(<store_id>)
autoLoad : true,
proxy : {
type : 'ajax',
url : networkObjsURL, // we load all records but I mentioned earlier that you can change this
reader : {
type : 'json',
idProperty : 'objValue'
},
}
});
I added peId field in netowrkModel because we want to query store later.
Ext.define('networkModel', {
extend : 'Ext.data.Model',
fields : [
{
name: 'objectValue'
},
{
name: 'peId',
type: 'int'
}
]
});
The last part is the networkStore function:
function networkStore(value) {
var store = Ext.getStore('networkStore');
var records = store.query('peId', value, false, true, true);
var hoverOutput = "";
if (records.length > 0) {
records.each(function(item) {
hoverOutput += item.get('objectValue') + "</br>";
});
}
console.log(hoverOutput);
return hoverOutput;
}
PS. I do not test above code.
However, IMO correct solution uses associations. I recommend you read this doc.
You should get to know concepts like schema, proxy, association and others.
When you join FrModel with NetworkModel by peId then you won't need NetworkStore and you build qtip in convert function based on that association.

Unable to validate a custom group using Knockout Validation

I cannot work out how to get the Knockout Validation plugin to validate a custom selection of viewmodel properties. I can call isValid() to validate the entire viewmodel successfully however.
I have followed the documentation set out here which covers the scenario and also checked all the answers I can find on stack overflow.
My code looks like this:
function MyViewModel() {
var self = this;
self.myproperty = ko.observableArray().extend({ minLength: { message: 'You must specify at least one item.'} })
self.anotherproperty = ko.observable().extend({ required: { params: true, message: 'You must supply a value.'} });
self.IsEntireModelValid = function() {
if (!self.isValid()) {
self.errors.showAllMessages();
return false;
}
else {
return true;
}
self.IsAnotherPropertyValidOnly = function() {
var errors = ko.validation.group(self.anotherproperty);
if (errors.length > 0) {
errors.showAllMessages();
return false;
}
else {
return true;
}
}
When I call self.IsAnotherPropertyValidOnly() the errors variable contains no errors, but when I call self.IsEntireModelValid() I get the correct response.
Could someone point out what I'm doing wrong?
You need to use errors().length.
self.IsAnotherPropertyValidOnly = function() {
var errors = ko.validation.group(self.anotherproperty);
if (errors().length > 0) {
errors.showAllMessages();
return false;
}
else {
return true;
}
}
http://jsfiddle.net/WY7V3/2/

Meteor.call issue in Meteor?

I need to know about the usage of Meteor.call. I did a simple example as shown below. The problem is that it never goes to insertDetails(). Can you please check the below code and suggest me what to do so that I don't get the Match Failed error.
Client.JS
Meteor.methods
({
//this method doesn't cal when using meteor.cal
insertDetails : function(adData, callback)
{
console.log(">>>>>>>>>>>>>>>>>>> ******* insertDetails ");
checkFields(adData);
var fields =
{
userID: adData.UserID,
fname: adData.fname,
lname: adData.lname,
dob: adData.dob
};
return Client.insert(fields, callback);
}
});
// SERVER-SIDE HELPERS ************************************
var nonEmpty = Match.Where(function(x) {return !!x;});
var checkFields = function(adData)
{
console.log(">>>>>>>>>>>>>>>>>>> checkFields ");
check(adData.userID, nonEmpty);
check(adData.fname, nonEmpty);
};
Insert.js
if (Meteor.isClient)
{
Template.hello.events({
'submit #addnewuserdetails': function (e,t)
{
if (typeof console !== 'undefined')
console.log(">>>>>>>>>>>>>>>>>>> Add button in details ");
e.preventDefault();
saveClientDetails();
}
});
}
var saveClientDetails = function()
{
console.log(">>>>>>>>>>>>>>>>>>> saveClientDetails ");
var fields = {
//ownerId: Meteor.userId(),
UserID : $('#userid').value
,fname : $('#fname').value
,lname :$('#lname').value
,dob : $('#dob').value
};
console.log(">>>>>>>>>>>>>>>>>>> fields.UserID "+fields.UserID);
//here cal to above insertDetails()
Meteor.call("insertDetails", fields, function(err, result)
{
if (!err)
{
console.log(">>>>>>>>>>>>>>>>>>> saveClientDetails Success");
}
else
{
console.log(">>>>>>>>>>>>>>>>>>> saveClientDetails ERROR "+err.reason);
}
});
};
The Match Failed error points to invalid data being rejected by your check function. My guess is that the problem is with user id: when you call the method you use UserID parameter, but then you check lowercase userID. Try fixing that and see whether it works. Also, try commenting out check call and see whether the rest of code is running. Also, how do you verify that the method was not called? Notice that log should be visible in the server console.

Categories