Related
I have installed mizzao:user-status package to track user activity like online, idle status.
I have added status to users collection:
import SimpleSchema from "simpl-schema";
const userSchema = new SimpleSchema({
status: {
type: Object,
optional: true,
},
"status.lastlogin": {
type: Object,
optional: true,
},
"status.lastlogin.date": {
type: Date,
optional: true,
},
"status.lastlogin.ipAddr": {
type: String,
optional: true,
},
"status.userAgent": {
type: String,
optional: true,
},
"status.idle": {
type: Boolean,
optional: true,
},
"status.lastActivity": {
type: Date,
optional: true,
},
"status.online": {
type: Boolean,
optional: true,
},
});
Meteor.users.attachSchema(userSchema);
On sign up page I have createUser code:
Accounts.createUser(
{ username, email, password },
async (error) => {
if (error && error.reason) {
setErrors({ signUpFailed: error.reason });
setIsLoading(false);
return;
}
navigate('/dashboard', { replace: true });
}
);
Whenever I try to register I get an error on the server:
Exception while invoking method 'createUser' Error: After filtering out keys not in the schema, your object is now empty
All fields in status are set to optional yet I am still getting this error. If I remove Meteor.users.attachSchema(userSchema); then create user works.
The error is pretty clear. In short it went through your schema, removed things that are not in it and found that it leaves you with empty object. As such you need to define all the other fields that is being used on the users collection. There are two ways how to avoid this issue. First is not to set any schema on the users collection, second is to properly describe everything that is being set and stored there. If you are adjusting the the user documents, then the second approach is best. Bellow is mine description, which also includes definitions for alanning:roles for quick reference. You can find more details on collection2 documentation:
https://github.com/Meteor-Community-Packages/meteor-collection2#attach-a-schema-to-meteorusers
const userSchema = new SimpleSchema({
username: {
type: String,
// For accounts-password, either emails or username is required, but not both. It is OK to make this
// optional here because the accounts-password package does its own validation.
optional: true
},
emails: {
type: Array,
// For accounts-password, either emails or username is required, but not both. It is OK to make this
// optional here because the accounts-password package does its own validation.
optional: true
},
'emails.$': {
type: Object
},
'emails.$.address': {
type: String,
regEx: SimpleSchema.RegEx.Email,
optional: true
},
'emails.$.verified': {
type: Boolean,
optional: true
},
'emails.$.primary': {
type: Boolean,
optional: true
},
createdAt: {
type: Date
},
profile: {
type: Object,
optional: true,
blackbox: true
},
services: {
type: Object,
optional: true,
blackbox: true
},
roles: {
type: Array,
optional: true
},
'roles.$': {
type: Object,
optional: true,
blackbox: true
},
// In order to avoid an 'Exception in setInterval callback' from Meteor
heartbeat: {
type: Date,
optional: true
}
})
You'll probably need to describe
username: {
type: String
},
emails: {
type: Array,
optional: true
},
at least, probably with other fields like profile
Sounds like what you are really looking for is https://docs.meteor.com/api/accounts-multi.html#AccountsServer-onCreateUser, which is the callback function you should use to add more fields to the user document when it is created. You don't really need to attach a schema for that, and from your comment the point of the schema was just to extend the user object somehow. If I understood that correctly, then onCreateUser is definitely the way to go.
I have a Meteor method which does an API call, then the response of the call is saved to the users collection. I'm using the Collection2 package with my project and I'm a little bit lost setting up my SimpleSchema for this.
Here is what the JSON response looks like from the API call:
[{"keyword":"2i","url":"http://example.com","title":"Example","timestamp":"2016-11-05
08:54:42","ip":"00.00.00.000","clicks":"2","user":"HweoSCY2ujscjJ9Zl"},{"keyword":"2j","url":"http://example.com","title":"YouTube","timestamp":"2016-11-06
02:11:18","ip":"00.00.00.000","clicks":"1","user":"HweoSCY2ujscjJ9Zl"},{"keyword":"2k","url":"http://example.com","title":"YouTube","timestamp":"2016-11-08
03:35:12","ip":"00.00.00.000","clicks":"0","user":"HweoSCY2ujscjJ9Zl"}]
Here's currently how I've been able to save this data to the users collection:
Meteor.users.update(Meteor.userId(), {
$set: { 'shortURLs.URLS': result.data }
});
This works and looks like this in the db:
My issue is that I'd like to have a SimpleSchema setup for this so that the "timestamp" will be saved as a Date instead of a String, but everytime I try and create a schema for it I just receive errors like "After filtering out keys not in the schema, your modifier is now empty". I have tried a lot of different variations to try and make it work but none of them have been successful, here's just currently where it's at:
Schema.ShortURLs = new SimpleSchema({
shortURLs: {
type: Object
},
'shortURLs.$': {
type: Object
},
'shortURLs.$.keyword': {
type: String,
optional: true,
label: "Keyword"
},
'shortURLs.$.url': {
type: String,
optional: true,
label: "URL"
},
'shortURLs.$.title': {
type: String,
optional: true,
label: "Title"
},
'shortURLs.$.timestamp': {
type: Date,
optional: true,
label: "Timestamp"
},
'shortURLs.$.ip': {
type: String,
optional: true,
label: "IP"
},
'shortURLs.$.clicks': {
type: String,
optional: true,
label: "Clicks"
},
'shortURLs.$.user': {
type: String,
optional: true,
label: "User"
},
});
This is then attached apart of a User Simple Schema:
...
shortURLs: {
type: Schema.ShortURLs,
optional: true
},
...
And I have that attached to the users collection:
Meteor.users.attachSchema(Schema.User);
I don't think there's an issue with how I have it attached as I have other SimpleSchemas setup the same way and they're working fine, I believe the issue is how I have this particular one written. Any help here would be extremely appreciated.
You need to define the shortURLs type in the Meteor.users collection as type: [Schema.ShortURLs], i.e. a list of type Schema.ShortURLs
Schema = {}
Schema.ShortURLs = new SimpleSchema({
keyword: {
type: String,
optional: true,
label: "Keyword"
},
url: {
type: String,
optional: true,
label: "URL"
},
title: {
type: String,
optional: true,
label: "Title"
},
timestamp: {
type: Date,
optional: true,
label: "Timestamp"
},
ip: {
type: String,
optional: true,
label: "IP"
},
clicks: {
type: String,
optional: true,
label: "Clicks"
},
user: {
type: String,
optional: true,
label: "User"
},
});
Schema.User = new SimpleSchema({
...
shortURLs: {
type: [Schema.ShortURLs],
optional: true
},
...
});
...
Meteor.users.attachSchema(Schema.User);
This works and insert {name: 'ok', color: '#ff0000'} to the categories when using Robomongo
db.requirements.update({_id: 'kJBZp2gA8TgNX3z2j'}, {$addToSet: {categories: {name: 'ok', color: '#ff0000'}}})
It does not from Meteor.
It inserts an empty object {} into categories array
EDIT
After SimpleSchema.debug = true; I have this log:
SimpleSchema.clean: filtered out value that would have affected key
"categories.$._id", which is not allowed by the schema
same for name and color thus inserting an empty object {}
The schema is:
categories: {
type: [{
_id: {
type: String
},
name: {
type: String
},
color: {
type: String
}
}],
optional: true
}
What would be the correct schema then ?
I don't grasp all the differences, but here is the new schema that now works. Thanks Matt K for the debug option pointer.
'categories.$._id': {
type: String,
optional: true
},
'categories.$.name': {
type: String,
optional: true
},
'categories.$.color': {
type: String,
optional: true
},
I want to get belongsTo record on datalist and show parent record fields.
Ext.define('MyApp.model.Customer', {
extend: 'Ext.data.Model',
config: {
fields: ['Id',
'EMail'],
hasMany: [{
model: 'MyApp.model.OutstandingInvoice',
name: 'OutstandingInvoice',
primaryKey: 'Id',
foreignKey: 'customerId',
foreignStore: 'OutstandingInvoices'
}]
}
});
Ext.define('MyApp.model.OutstandingInvoice', {
extend: 'Ext.data.Model',
config: {
fields: [
'InvoiceDate',
'InvoiceID',
'customerId'
],
belongsTo: [{
model: 'MyApp.model.Customer',
name: 'Customer',
primaryKey: 'Id',
foreignKey: 'customerId',
foreignStore: 'Customers'
}]
}
});
Ext.define('MyApp.store.OutstandingInvoices', {
extend: 'Ext.data.Store',
config: {
model: 'MyApp.model.OutstandingInvoice',
storeId: 'OutstandingInvoiceStore',
proxy: {
useDefaultXhrHeader: false,
type: 'ajax',
url : 'http://localhost/getOutstandingInvoices',
reader: {
type: 'json'
}
},
autoLoad: false
}
});
Ext.define('MyApp.store.Customers', {
extend: 'Ext.data.Store',
config: {
model: 'MyApp.model.Customer',
storeId: 'CustomerStore',
proxy: {
useDefaultXhrHeader: false,
type: 'ajax',
url : 'http://localhost/getCustJList',
reader: {
type: 'json'
}
},
autoLoad: false,
sorters: [{
property : 'FName',
direction: 'ASC'
}]
}
});
Ext.define('MyApp.view.OutstandingInvoices', {
extend: 'Ext.Panel',
xtype: 'outstandingInvoicesXType',
config: {
cls : 'invoiceSummaryCls',
scrollable: 'vertical',
items: [
{
xtype: 'titlebar',
docked: 'top',
title: 'Outstanding Invoices'
},
{
xtype : 'list',
scrollable: false,
store: 'OutstandingInvoiceStore',
cls : 'p10',
itemTpl: [
'<div>Invoice # {InvoiceID}</div>',
'<div>{InvoiceDate}</div>',
'<div>{Customer.Email}</div>', // I want to show Customer name here as its belongsTo Customer
],
listeners: {
itemtap:function (list, index, targe, rec, e, eOpts) {
console.log(rec)
}
}
}
]
}
});
I want to show Customer name in datalist but having issue with association or Xtemplate
I am getting this error
Uncaught Error: [ERROR][Ext.XTemplate#apply] Cannot read property 'Email' of undefined
Please help me out in this.
I'd recommend reading this article, its quite lengthy but the final List section is similar to your example.
I think the key point is you're not going to need separate stores. Sencha is going to create those automatically off the back of the associations. Make sure you move the proxies onto the models and set autoLoad: true
I want to populate the combobox dynamically based on the data I received from thr Url(which is servlet)
Below is my ExtJS code :
{
xtype:'combo',
id: 'shoutoutsTags',
fieldLabel: 'Tag',
value: '',
mode: 'local',
width: 200,
store: new Ext.data.JsonStore({
id:'ms',
url:'http://localhost:8080/ezdi/extServlet',
//totalProperty:'totalCount',
root:'rows',
fields:[
{name:'un'},
{name:'pwd'}
],
autoLoad:true
}),
displayField: 'un',
valueField: 'pwd',
typeAhead:true,
minChars:1,
forceSelection: true,
triggerAction: 'all',
hideTrigger:true
//hiddenName: 'mytag'
}
But I am getting below error and my Url is not being called:
msg : "You are using a ServerProxy but have not supplied it with a url."
sourceClass : "Ext.data.proxy.Server"
sourceMethod : "buildUrl" uncaught exception: You are using a ServerProxy
but have not supplied it with a
url.
Suggest me how can I overcome this error.
Ext.define("modelname", {
extend: 'Ext.data.Model',
proxy: {
type: 'ajax',
url : '/myServlet',
method:'POST',
reader: {
type: 'json',
root: 'rows'
//,totalProperty: 'totalCount'
}
},
fields: [
{name: 'name', mapping: 'name'}
]
});
var ds = Ext.create('Ext.data.Store', {
pageSize: 10,
model: 'modelName'
});
Your store needs to be updated to use the new Ext JS 4 data model:
var store = Ext.create('Ext.data.Store', {
model: 'MyNamespace.StoreModel',
proxy: {
type: 'ajax',
url: 'http://localhost:8080/ezdi/extServlet',
reader: {
type: 'json',
root: 'rows',
totalProperty: 'totalCount'
}
}
});
You'll notice here that the store has a property 'model', which is a string, and that there is no field mapping. This is because you'll also need to create a model for the store to reference, like so:
Ext.define('MyNamespace.StoreModel', {
extend: 'Ext.data.Model',
fields: [
{name:'un'},
{name:'pwd'}
]
});
Hope this helps!
Thats not a valid url, you'll want just '/ezdi/extServlet'.