Rxjs says, Rx.DOM is undefined - dom

I am trying out the simple keypress example,
var input = document.getElementById('input');
var source = Rx.DOM.keypress(input);
var subscription = source.subscribe(
function (x) {
console.log('Next!');
},
function (err) {
console.log('Error: ' + err);
},
function () {
console.log('Completed');
});
And i have included rx.js and rx.binding.js in the index.html. But it says,
Rx.DOM is undefined.
I am not seeing DOM function in both the rx files as well.

It comes as a different extension https://github.com/Reactive-Extensions/RxJS-DOM

Related

Element is not clickable inside of a for loop in protractor

I am using protractor-cucumber frame work with protractor 5.2.2 and mssql 3.3.0.We have a requirement of get db values,i am able to get db data values into my protractor code, But i am not able to click on a element with that db value.My code is given below.
function ConnectDB() {
var config = {
user: 'sam',
password: 'Passw0rd',
server: 'xxxxxx',
port: '50866',
database: 'testDB',
options: {
trustedConnection: true
}
}
sql.connect(config, function (err) {
if (err) console.log(err+" db connection failed");
var request = new sql.Request();
request.query('SELECT * FROM Locations WHERE ID = 2', function (err, loc){
if (err) console.log(err+" loc_name failed");
var loc_count= loc.length;
console.log(loc_count);
console.log(loc[0].Location_name);
var i;
for (i=0; i<loc_count; i++){
if(loc_count!=0 & loc_count%10==0){
element(by.css(.publish)).click();
}
element(by.cssContainingText("span", loc[i].Location_name)).click();
console.log(loc[i].Location_name);
browser.sleep(4000);
element(by.css(.post)).sendKeys("test");
element(by.css(.submit)).click();
}
});
});
}
Here the click() and senkeys() functions inside of the for loop is not working.But i am able to console the values of loc_count and loc[i].Location_name.How can i solve this?Thanks in advance.
The root cause of your issue is that the scripts of loop body almost executed async. All Protractor APIs are async. Thus the sendKeys click(), sleep() inside the loop are executed async. But the loop iterate sync.
This lead to when the i==loc_count, the click()/sendKeys()/sleep() of the i==0 have not been executed (They are async).
One solution is to use Closure to keep the i for each iteration. Another solution is use ES6 async/await.
Below is the code example of solution one:
var i;
for (i=0; i<loc_count; i++){
(function(j){
if(loc_count!=0 && loc_count%10==0){
element(by.css('.publish')).click();
}
element(by.cssContainingText("span", loc[j].Location_name)).click();
console.log(loc[j].Location_name);
browser.sleep(4000);
element(by.css('.post')).sendKeys("test");
element(by.css('.submit')).click();
})(i)
}
As yong stated it is because your for loop is synchronous and the protractor actions are async. You either need to implement async/await or use the then callbacks to make it work correctly.
Async/Await option:
request.query('SELECT * FROM Locations WHERE ID = 2', async function (err, loc){
if (err) console.log(err+" loc_name failed");
var loc_count= loc.length;
console.log(loc_count);
console.log(loc[0].Location_name);
var i;
for (i=0; i<loc_count; i++){
if(loc_count!=0 & loc_count%10==0){
await element(by.css(.publish)).click();
}
await element(by.cssContainingText("span", loc[i].Location_name)).click();
console.log(loc[i].Location_name);
await browser.sleep(4000);
await element(by.css(.post)).sendKeys("test");
await element(by.css(.submit)).click();
}
});
To use the then callbacks it would be a little more difficult to handle your if block correctly but essentially you will need to do something like this to get it to work.
element(by.cssContainingText("span", loc[i].Location_name)).click().then(() -> {
console.log(loc[i].Location_name);
browser.sleep(4000).then(() => {
element(by.css(.post)).sendKeys("test").then(() => {
element(by.css(.submit)).click();
});
});
});
The first option is far easier to read and implement correctly.
Try to use :-
var elm = element(by.id("myid"));
browser.executeScript("arguments[0].click();", elm.getWebElement());

Meteor onRendered function and access to Collections

When user refresh a certain page, I want to set some initial values from the mongoDB database.
I tried using the onRendered method, which in the documentation states will run when the template that it is run on is inserted into the DOM. However, the database is not available at that instance?
When I try to access the database from the function:
Template.scienceMC.onRendered(function() {
var currentRad = radiationCollection.find().fetch()[0].rad;
}
I get the following error messages:
Exception from Tracker afterFlush function:
TypeError: Cannot read property 'rad' of undefined
However, when I run the line radiationCollection.find().fetch()[0].rad; in the console I can access the value?
How can I make sure that the copy of the mongoDB is available?
The best way for me was to use the waitOn function in the router. Thanks to #David Weldon for the tip.
Router.route('/templateName', {
waitOn: function () {
return Meteor.subscribe('collectionName');
},
action: function () {
// render all templates and regions for this route
this.render();
}
});
You need to setup a proper publication (it seems you did) and subscribe in the route parameters. If you want to make sure that you effectively have your data in the onRendered function, you need to add an extra step.
Here is an example of how to make it in your route definition:
this.templateController = RouteController.extend({
template: "YourTemplate",
action: function() {
if(this.isReady()) { this.render(); } else { this.render("yourTemplate"); this.render("loading");}
/*ACTION_FUNCTION*/
},
isReady: function() {
var subs = [
Meteor.subscribe("yoursubscription1"),
Meteor.subscribe("yoursubscription2")
];
var ready = true;
_.each(subs, function(sub) {
if(!sub.ready())
ready = false;
});
return ready;
},
data: function() {
return {
params: this.params || {}, //if you have params
yourData: radiationCollection.find()
};
}
});
In this example you get,in the onRendered function, your data both using this.data.yourData or radiationCollection.find()
EDIT: as #David Weldon stated in comment, you could also use an easier alternative: waitOn
I can't see your collection, so I can't guarantee that rad is a key in your collection, that said I believe your problem is that you collection isn't available yet. As #David Weldon says, you need to guard or wait on your subscription to be available (remember it has to load).
What I do in ironrouter is this:
data:function(){
var currentRad = radiationCollection.find().fetch()[0].rad;
if (typeof currentRad != 'undefined') {
// if typeof currentRad is not undefined
return currentRad;
}
}

sails.js model reference error

I am studying Sails.js and I have a question.
I made a model object using "sails generate model site" command.
and I made init.js file in config directory for my cronjob.
everytime system launched, cronjob starts from this init.js.
this is init.js
var fs = require('fs'),
sails = require('sails'),
async = require('async');
exports.initSite = function () {
'use strict';
sails.log.debug('init method start!');
async.waterfall([
function (callback) {
Site.find().exec(function (err, sites) {
if (err) {
callback(err);
}
if (sites) {
async.forEachSeries(sites,
function (siteData, callback2) {
siteData.remove(function (err) {
if (err) {
callback(err);
}
callback2();
});
}, function (err) {
if (err) {
callback(err);
}
callback();
});
} else {
callback();
}
});
},
function (callback) {
var jsonData = fs.readFile('./urls.json', 'utf8', function (err, datas) {
if (err) {
callback(err);
}
callback(null, datas);
});
},
function (datas, callback) {
var urls = JSON.parse(datas);
for (var key in urls) {
var value = urls[key];
var site = new Site({
siteId: value.id,
name: value.name,
url: value.url,
category: value.category
});
site.save(function(err){
if (err) {
callback(err);
}
});
}
callback();
}
],function(err){
if (err) {
sails.log.error('ERROR!');
}
sails.log.info('INIT OK');
});
};
and I read this init.js from app.js like this.
in app.js
require(__dirname + '/config/init').initSite();
but everytime I launch application, console messages says ReferenceError: Site is not defined.
I don't know why init.js can't read 'Site (model object)'.
your advice is very thankful for me.
(sorry for my bad english.... ;_;)
Sailsjs does not load your models until it has been "lifted". You need to run sails lift first from within the directory that your app.js file has been defined, then you can run this chron job. After sails loads, all your models will be exposed as globals. The code in init.js should be called from app.js after sails lifts.
This is based on the discussion about the above topic, so it's not exactly a "cron job" but it can be executed like one and also have access to all the nice features that Sails.js provides, including models.
You can use node-schedule.
So this is what i did.
Install node-schedule
npm install –save node-schedule
Create a crontab file in config/crontab.js
Paste this code in the crontab.js. What i am doing here is creating a method where i require my cronjob, finally i append the method to the jsonArray, so the config/bootstrap.js will execute the file.
module.exports.crontab = {
/*
* The asterisks in the key are equivalent to the
* schedule setting in crontab, i.e.
* minute hour day month day-of-week year
* so in the example below it will run every minute
*/
crons:function()
{
var jsonArray = [];
jsonArray.push({interval:’*/1 * * * * * ‘,method:’mytest’});
// add more cronjobs if you want like below
// but dont forget to add a new method…
//jsonArray.push({interval:’*/1 * * * * * ‘,method:’anothertest’});
return jsonArray;
},
// declare the method mytest
// and add it in the crons function
mytest: function(){
require(‘../crontab/mytest.js’).run();
}
/*
anothertest:function(){
require(‘../crontab/anothertest.js’).run();
}
*/
};
Open your config/bootstrap.js and add this code
module.exports.bootstrap = function(cb) {
_.extend(sails.hooks.http.app.locals, sails.config.http.locals);
// add the lines from here
// bootstrapping all the cronjobs in the crontab folder
var schedule = require(‘node-schedule’);
sails.config.crontab.crons().forEach(function(item){
schedule.scheduleJob(item.interval,sails.config.crontab[item.method]);
});
// It’s very important to trigger this callback method when you are finished
// with the bootstrap! (otherwise your server will never lift, since it’s waiting on the bootstrap)
cb();
};
Finally run sails l and you should see a message running every minute.

When using Meteor I cannot access the collection from client console?

This is the strangest thing, for some reason even with autopublish turned on, I cannot access the collection from browser console. The code below is a simple list program where you can enter items into the collection and it will appear as a list on the screen. In console when I try to access the database by typing People.find() or People.find().fetch() it brings up an error 'ReferenceError: Can't find variable: People'
How come this is happening I have autopublish on, so I thought I can access the collection from the client?
Code:
var People = new Meteor.Collection("people");
if (Meteor.isClient) {
console.log(People.find());
Template.personList.people = function () {
return People.find();
};
Template.personForm.events({
'click button': function(e, t) {
var el = t.find("#name");
People.insert({ name: el.value });
el.value = "";
}
});
Template.person.editing = function () {
return Session.get("edit-" + this._id);
};
Template.person.rendered = function () {
var input = this.find("input");
if(input) {
input.focus();
}
};
Template.person.events({
'click .name': function (e, t) {
Session.set("edit-" + t.data._id, true);
},
'keypress input': function (e, t) {
if (e.keyCode == 13) {
People.update(t.data._id, { $set: { name: e.currentTarget.value }});
Session.set("edit-" + t.data._id, false);
}
},
'click .del': function (e, t) {
People.remove(t.data._id);
}
});
}
You don't have to use # unless you're using coffeescript. In plain javascript remove the var so your variable can be accessed anywhere outside of the file (including the chrome console):
var People = new Meteor.Collection("people");
becomes
People = new Meteor.Collection("people");
To use coffeescript use a .coffee extension and run meteor add coffeescript to allow meteor to compile coffeescript files to js files
to answer your question # is used for CoffeeScript (Javascript Alternative), you can add the meteor package for it and then write your app in that language. Learn about it here http://coffeescript.org

How to get Meteor.Call to return value for template?

I've tried to understand this post regarding this concept, however, I'm failing to get it. I have the following simple setup:
/server/test.js
Meteor.methods({
abc: function() {
var result = {};
result.foo = "Hello ";
result.bar = "World!";
return result;
}
});
/client/myapp.js
var q = Meteor.call('abc');
console.log(q);
This structure returns to the console undefined.
If I change the myapp.js file to:
Meteor.call('abc', function(err, data) {
!err ? console.log(data) : console.log(err);
}
I receive the Object in my console.
Ideally this is what I'd like to be able to do, but it doesn't work, stating in the console: Cannot read property 'greeting' of undefined
/client/myapp.js
var q = Meteor.call('abc');
Template.hello.greeting = function() {
return q.foo;
}
Any help in passing the data from the server object into the template would be greatly appreciated. I'm still learning JavaScript & Meteor.
Thanks!
From the Meteor.call documentation:
On the client, if you do not pass a callback and you are not inside a stub, call will return undefined, and you will have no way to get the return value of the method. That is because the client doesn't have fibers, so there is not actually any way it can block on the remote execution of a method.
So, you'll want to do it like this:
Meteor.call('abc', function(err, data) {
if (err)
console.log(err);
Session.set('q', data);
});
Template.hello.greeting = function() {
return Session.get('q').foo;
};
This will reactively update the template once the data is available.
This happens because Npm.require has Async behavior. That's the reason that you have to write a callback for Meteor.call.
But there is a solution, just use install(mrt add npm) and you'll get a function named Meteor.sync(//...) with this you can do both games: sync and async in your Meteor.call().
Reference: http://www.sitepoint.com/create-a-meteor-app-using-npm-module/
You can get the return value of a Meteor method for use in a template by using a reactive variable. Check out the working demonstration on Meteorpad
I went for a ghetto solution. But, it works for me, which is what matters, to me. Below is my code, which, in concept, I think, solves OP's problem.
In the client's main.js:
Meteor.setInterval(function() {
confirmLogin();
}, 5000);
This runs the confirmLogin() function every five seconds.
The confirmLogin function (in the client's main.js):
function confirmLogin() {
Meteor.call('loggedIn', function (error, result) {
Session.set("loggedIn", result);
});
}
The loggedIn method (in the server's main.js):
loggedIn: function () {
var toReturn = false;
var userDetails = Meteor.user();
if (typeof userDetails["services"] !== "undefined") {
if (typeof userDetails["services"]["facebook"] != "undefined") {
toReturn = true;
}
}
return toReturn;
},
The relevant helper:
loggedIn: function () {
return Session.get("loggedIn");
}