aurelia validation property expression help needed - validation

I am trying to match a single aurelia validation to a bunch of properties in a form. E.g. every field with a property name of ssid in an array of objects that map to rows in a table. The validation docs say that the ensure clauses can have a property expression which sounds like what I need. I'm using the validation from
{ValidationRules, ValidationController} from 'aurelia-validation';
I've got validation working for a single property using
ValidationRules.ensure('apPwd').displayName('XY AP Password').maxLength(32).minLength(8).on(this);
where apPwd is the property expression.
But I can't find any spec for property expressions. Most examples in the aurelia docs just show a single property name. The most complicated I've seen are things piped together with | or & (whatever that is).
Can anyone point me to a spec or help with my specific problem? Or maybe I should just ditch this package and roll my own code?

I think this can help you out:
This is validate.ts
import { autoinject } from 'aurelia-framework';
import { ValidationRules, ValidationController } from 'aurelia-validation';
#autoinject
export class Validate {
numberField: number;
controller: any;
constructor (
private validationController: ValidationController
) {
this.controller = validationController;
ValidationRules.customRule(
'nummer',
(value, obj, min, max) => {
let numberValue: number = parseInt(value);
return value === null || value === undefined || Number.isInteger(nummer) && nummer >= min && nummer <= max;
},
`\${$displayName} must be an integer between \${$config.min} and \${$config.max}.`,
(min, max) => ({ min, max })
);
ValidationRules
.ensure((m: this) => m.numberField)
.required()
.withMessage('Rutan får inte vara tom.')
.satisfiesRule('nummer', 1, 100)
/*.satisfies((value: any, object?: any) => {
console.log(value);
if (value >= 1 && value <= 100) {
return true;
}
else {
return false;
}
})
.withMessage(`The number must be between - 100.`)*/
.ensure((m: this) => m.numberField).required()
.on(this);
}
submit(): void {
this.executeValidation();
}
executeValidation(): void {
this.controller.validate()
.then(errors => {
if (errors.length === 0) {
console.log('all good!');
} else {
console.log('all errors!');
}
});
}
}
And this is validate.pug (in my case, but you can use a html page if you like)
template
section.au-animate
h2 Validate
form(role="form")
.form-group
label Number
input#meetingSubject.form-control(type="text" value.bind="numberField & validate")
button.btn.btn-lg.btn-primary(click.delegate='submit()') Validate
div
h3 ${'latestValidationResult'}
ul(if.bind='controller.errors.length')
li(repeat.for='error of controller.errors') ${error.message}

Not sure if I understood your question, but I think you're looking for ensureObject:
ValidationRules
.ensureObject()
.satisfies(obj => {
return obj.property1 === 'test' && obj.property2.indexOf('test2') !== -1
})
.withMessage('Some error message.')
.on(this);

Related

How can I run useEffect on state change only and not on mount? [duplicate]

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.
After an AJAX request, sometimes my application may return an empty object, like:
var a = {};
How can I check whether that's the case?
ECMA 5+:
// because Object.keys(new Date()).length === 0;
// we have to do some additional check
obj // 👈 null and undefined check
&& Object.keys(obj).length === 0
&& Object.getPrototypeOf(obj) === Object.prototype
Note, though, that this creates an unnecessary array (the return value of keys).
Pre-ECMA 5:
function isEmpty(obj) {
for(var prop in obj) {
if(Object.prototype.hasOwnProperty.call(obj, prop)) {
return false;
}
}
return JSON.stringify(obj) === JSON.stringify({});
}
jQuery:
jQuery.isEmptyObject({}); // true
lodash:
_.isEmpty({}); // true
Underscore:
_.isEmpty({}); // true
Hoek
Hoek.deepEqual({}, {}); // true
ExtJS
Ext.Object.isEmpty({}); // true
AngularJS (version 1)
angular.equals({}, {}); // true
Ramda
R.isEmpty({}); // true
If ECMAScript 5 support is available, you can use Object.keys():
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
For ES3 and older, there's no easy way to do this. You'll have to loop over the properties explicitly:
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
return false;
}
return true;
}
For those of you who have the same problem but use jQuery, you can use jQuery.isEmptyObject.
Performance
Today 2020.01.17, I performed tests on macOS High Sierra 10.13.6 on Chrome v79.0, Safari v13.0.4, and Firefox v72.0; for the chosen solutions.
Conclusions
Solutions based on for-in (A, J, L, M) are fastest
Solutions based on JSON.stringify (B, K) are slow
Surprisingly, the solution based on Object (N) is also slow
NOTE: This table does not match the photo below.
Details
There are 15 solutions presented in the snippet below.
If you want to run a performance test on your machine, click HERE.
This link was updated 2021.07.08, but tests originally were performed here - and results in the table above came from there (but now it looks like that service no longer works).
var log = (s, f) => console.log(`${s} --> {}:${f({})} {k:2}:${f({ k: 2 })}`);
function A(obj) {
for (var i in obj) return false;
return true;
}
function B(obj) {
return JSON.stringify(obj) === "{}";
}
function C(obj) {
return Object.keys(obj).length === 0;
}
function D(obj) {
return Object.entries(obj).length === 0;
}
function E(obj) {
return Object.getOwnPropertyNames(obj).length === 0;
}
function F(obj) {
return Object.keys(obj).length === 0 && obj.constructor === Object;
}
function G(obj) {
return typeof obj === "undefined" || !Boolean(Object.keys(obj)[0]);
}
function H(obj) {
return Object.entries(obj).length === 0 && obj.constructor === Object;
}
function I(obj) {
return Object.values(obj).every((val) => typeof val === "undefined");
}
function J(obj) {
for (const key in obj) {
if (hasOwnProperty.call(obj, key)) {
return false;
}
}
return true;
}
function K(obj) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
return false;
}
}
return JSON.stringify(obj) === JSON.stringify({});
}
function L(obj) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) return false;
}
return true;
}
function M(obj) {
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
return false;
}
}
return true;
}
function N(obj) {
return (
Object.getOwnPropertyNames(obj).length === 0 &&
Object.getOwnPropertySymbols(obj).length === 0 &&
Object.getPrototypeOf(obj) === Object.prototype
);
}
function O(obj) {
return !(Object.getOwnPropertyNames !== undefined
? Object.getOwnPropertyNames(obj).length !== 0
: (function () {
for (var key in obj) break;
return key !== null && key !== undefined;
})());
}
log("A", A);
log("B", B);
log("C", C);
log("D", D);
log("E", E);
log("F", F);
log("G", G);
log("H", H);
log("I", I);
log("J", J);
log("K", K);
log("L", L);
log("M", M);
log("N", N);
log("O", O);
You can use Underscore.js.
_.isEmpty({}); // true
if(Object.getOwnPropertyNames(obj).length === 0){
//is empty
}
see http://bencollier.net/2011/04/javascript-is-an-object-empty/
How about using JSON.stringify? It is almost available in all modern browsers.
function isEmptyObject(obj){
return JSON.stringify(obj) === '{}';
}
There is a simple way if you are on a newer browser.
Object.keys(obj).length === 0
Old question, but just had the issue. Including JQuery is not really a good idea if your only purpose is to check if the object is not empty. Instead, just deep into JQuery's code, and you will get the answer:
function isEmptyObject(obj) {
var name;
for (name in obj) {
if (obj.hasOwnProperty(name)) {
return false;
}
}
return true;
}
Using Object.keys(obj).length (as suggested above for ECMA 5+) is 10 times slower for empty objects! keep with the old school (for...in) option.
Tested under Node, Chrome, Firefox and IE 9, it becomes evident that for most use cases:
(for...in...) is the fastest option to use!
Object.keys(obj).length is 10 times slower for empty objects
JSON.stringify(obj).length is always the slowest (not suprising)
Object.getOwnPropertyNames(obj).length takes longer than Object.keys(obj).length can be much longer on some systems.
Bottom line performance wise, use:
function isEmpty(obj) {
for (var x in obj) { return false; }
return true;
}
or
function isEmpty(obj) {
for (var x in obj) { if (obj.hasOwnProperty(x)) return false; }
return true;
}
See detailed testing results and test code at Is object empty?
My take:
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
var a = {
a: 1,
b: 2
}
var b = {}
console.log(isEmpty(a)); // false
console.log(isEmpty(b)); // true
Just, I don't think all browsers implement Object.keys() currently.
I am using this.
function isObjectEmpty(object) {
var isEmpty = true;
for (keys in object) {
isEmpty = false;
break; // exiting since we found that the object is not empty
}
return isEmpty;
}
Eg:
var myObject = {}; // Object is empty
var isEmpty = isObjectEmpty(myObject); // will return true;
// populating the object
myObject = {"name":"John Smith","Address":"Kochi, Kerala"};
// check if the object is empty
isEmpty = isObjectEmpty(myObject); // will return false;
from here
Update
OR
you can use the jQuery implementation of isEmptyObject
function isEmptyObject(obj) {
var name;
for (name in obj) {
return false;
}
return true;
}
Just a workaround. Can your server generate some special property in case of no data?
For example:
var a = {empty:true};
Then you can easily check it in your AJAX callback code.
Another way to check it:
if (a.toSource() === "({})") // then 'a' is empty
EDIT:
If you use any JSON library (f.e. JSON.js) then you may try JSON.encode() function and test the result against empty value string.
1. Using Object.keys
Object.keys will return an Array, which contains the property names of the object. If the length of the array is 0, then we know that the object is empty.
function isEmpty(obj) {
return Object.keys(obj).length === 0 && obj.constructor === Object;
}
We can also check this using Object.values and Object.entries.
This is typically the easiest way to determine if an object is empty.
2. Looping over object properties with for…in
The for…in statement will loop through the enumerable property of object.
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
return false;
}
return true;
}
In the above code, we will loop through object properties and if an object has at least one property, then it will enter the loop and return false. If the object doesn’t have any properties then it will return true.
#3. Using JSON.stringify
If we stringify the object and the result is simply an opening and closing bracket, we know the object is empty.
function isEmptyObject(obj){
return JSON.stringify(obj) === '{}';
}
4. Using jQuery
jQuery.isEmptyObject(obj);
5. Using Underscore and Lodash
_.isEmpty(obj);
Resource
function isEmpty(obj) {
for(var i in obj) { return false; }
return true;
}
The following example show how to test if a JavaScript object is empty, if by empty we means has no own properties to it.
The script works on ES6.
const isEmpty = (obj) => {
if (obj === null ||
obj === undefined ||
Array.isArray(obj) ||
typeof obj !== 'object'
) {
return true;
}
return Object.getOwnPropertyNames(obj).length === 0;
};
console.clear();
console.log('-----');
console.log(isEmpty('')); // true
console.log(isEmpty(33)); // true
console.log(isEmpty([])); // true
console.log(isEmpty({})); // true
console.log(isEmpty({ length: 0, custom_property: [] })); // false
console.log('-----');
console.log(isEmpty('Hello')); // true
console.log(isEmpty([1, 2, 3])); // true
console.log(isEmpty({ test: 1 })); // false
console.log(isEmpty({ length: 3, custom_property: [1, 2, 3] })); // false
console.log('-----');
console.log(isEmpty(new Date())); // true
console.log(isEmpty(Infinity)); // true
console.log(isEmpty(null)); // true
console.log(isEmpty(undefined)); // true
The correct answer is:
function isEmptyObject(obj) {
return (
Object.getPrototypeOf(obj) === Object.prototype &&
Object.getOwnPropertyNames(obj).length === 0 &&
Object.getOwnPropertySymbols(obj).length === 0
);
}
This checks that:
The object's prototype is exactly Object.prototype.
The object has no own properties (regardless of enumerability).
The object has no own property symbols.
In other words, the object is indistinguishable from one created with {}.
jQuery have special function isEmptyObject() for this case:
jQuery.isEmptyObject({}) // true
jQuery.isEmptyObject({ foo: "bar" }) // false
Read more on http://api.jquery.com/jQuery.isEmptyObject/
Caveat! Beware of JSON's limitiations.
javascript:
obj={ f:function(){} };
alert( "Beware!! obj is NOT empty!\n\nobj = { f:function(){} }" +
"\n\nJSON.stringify( obj )\n\nreturns\n\n" +
JSON.stringify( obj ) );
displays
Beware!! obj is NOT empty!
obj = { f:function(){} }
JSON.stringify( obj )
returns
{}
To really accept ONLY {}, the best way to do it in Javascript using Lodash is:
_.isEmpty(value) && _.isPlainObject(value)
In addition to Thevs answer:
var o = {};
alert($.toJSON(o)=='{}'); // true
var o = {a:1};
alert($.toJSON(o)=='{}'); // false
it's jquery + jquery.json
Sugar.JS provides extended objects for this purpose. The code is clean and simple:
Make an extended object:
a = Object.extended({})
Check it's size:
a.size()
Pure Vanilla Javascript, and full backward compatibility
function isObjectDefined (Obj) {
if (Obj === null || typeof Obj !== 'object' ||
Object.prototype.toString.call(Obj) === '[object Array]') {
return false
} else {
for (var prop in Obj) {
if (Obj.hasOwnProperty(prop)) {
return true
}
}
return JSON.stringify(Obj) !== JSON.stringify({})
}
}
console.log(isObjectDefined()) // false
console.log(isObjectDefined('')) // false
console.log(isObjectDefined(1)) // false
console.log(isObjectDefined('string')) // false
console.log(isObjectDefined(NaN)) // false
console.log(isObjectDefined(null)) // false
console.log(isObjectDefined({})) // false
console.log(isObjectDefined([])) // false
console.log(isObjectDefined({a: ''})) // true
IsEmpty Object, unexpectedly lost its meaning i.e.: it's programming semantics, when our famous guru from Yahoo introduced the customized non-enumerable Object properties to ECMA and they got accepted.
[ If you don't like history - feel free to skip right to the working code ]
I'm seeing lots of good answers \ solutions to this question \ problem.
However, grabbing the most recent extensions to ECMA Script is not the honest way to go. We used to hold back the Web back in the day to keep Netscape 4.x, and Netscape based pages work and projects alive, which (by the way) were extremely primitive backwards and idiosyncratic, refusing to use new W3C standards and propositions [ which were quite revolutionary for that time and coder friendly ] while now being brutal against our own legacy.
Killing Internet Explorer 11 is plain wrong! Yes, some old warriors that infiltrated Microsoft remaining dormant since the "Cold War" era, agreed to it - for all the wrong reasons. - But that doesn't make it right!
Making use, of a newly introduced method\property in your answers and handing it over as a discovery ("that was always there but we didn't notice it"), rather than a new invention (for what it really is), is somewhat 'green' and harmful. I used to make such mistakes some 20 years ago when I still couldn't tell what's already in there and treated everything I could find a reference for, as a common working solution...
Backward compatibility is important !
We just don't know it yet. That's the reason I got the need to share my 'centuries old' generic solution which remains backward and forward compatible to the unforeseen future.
There were lots of attacks on the in operator but I think the guys doing that have finally come to senses and really started to understand and appreciate a true Dynamic Type Language such as JavaScript and its beautiful nature.
My methods aim to be simple and nuclear and for reasons mentioned above, I don't call it "empty" because the meaning of that word is no longer accurate. Is Enumerable, seems to be the word with the exact meaning.
function isEnum( x ) { for( var p in x )return!0; return!1 };
Some use cases:
isEnum({1:0})
true
isEnum({})
false
isEnum(null)
false
Thanks for reading!
Best one-liner solution I could find (updated):
isEmpty = obj => !Object.values(obj).filter(e => typeof e !== 'undefined').length;
console.log(isEmpty({})) // true
console.log(isEmpty({a: undefined, b: undefined})) // true
console.log(isEmpty({a: undefined, b: void 1024, c: void 0})) // true
console.log(isEmpty({a: [undefined, undefined]})) // false
console.log(isEmpty({a: 1})) // false
console.log(isEmpty({a: ''})) // false
console.log(isEmpty({a: null, b: undefined})) // false
Another alternative is to use is.js (14kB) as opposed to jquery (32kB), lodash (50kB), or underscore (16.4kB). is.js proved to be the fastest library among aforementioned libraries that could be used to determine whether an object is empty.
http://jsperf.com/check-empty-object-using-libraries
Obviously all these libraries are not exactly the same so if you need to easily manipulate the DOM then jquery might still be a good choice or if you need more than just type checking then lodash or underscore might be good. As for is.js, here is the syntax:
var a = {};
is.empty(a); // true
is.empty({"hello": "world"}) // false
Like underscore's and lodash's _.isObject(), this is not exclusively for objects but also applies to arrays and strings.
Under the hood this library is using Object.getOwnPropertyNames which is similar to Object.keys but Object.getOwnPropertyNames is a more thorough since it will return enumerable and non-enumerable properties as described here.
is.empty = function(value) {
if(is.object(value)){
var num = Object.getOwnPropertyNames(value).length;
if(num === 0 || (num === 1 && is.array(value)) || (num === 2 && is.arguments(value))){
return true;
}
return false;
} else {
return value === '';
}
};
If you don't want to bring in a library (which is understandable) and you know that you are only checking objects (not arrays or strings) then the following function should suit your needs.
function isEmptyObject( obj ) {
return Object.getOwnPropertyNames(obj).length === 0;
}
This is only a bit faster than is.js though just because you aren't checking whether it is an object.
I know this doesn't answer 100% your question, but I have faced similar issues before and here's how I use to solve them:
I have an API that may return an empty object. Because I know what fields to expect from the API, I only check if any of the required fields are present or not.
For example:
API returns {} or {agentID: '1234' (required), address: '1234 lane' (opt),...}.
In my calling function, I'll only check
if(response.data && response.data.agentID) {
do something with my agentID
} else {
is empty response
}
This way I don't need to use those expensive methods to check if an object is empty. The object will be empty for my calling function if it doesn't have the agentID field.
We can check with vanilla js with handling null or undefined check also as follows,
function isEmptyObject(obj) {
return !!obj && Object.keys(obj).length === 0 && obj.constructor === Object;
}
//tests
isEmptyObject(new Boolean()); // false
isEmptyObject(new Array()); // false
isEmptyObject(new RegExp()); // false
isEmptyObject(new String()); // false
isEmptyObject(new Number()); // false
isEmptyObject(new Function()); // false
isEmptyObject(new Date()); // false
isEmptyObject(null); // false
isEmptyObject(undefined); // false
isEmptyObject({}); // true
I liked this one I came up with, with the help of some other answers here. Thought I'd share it.
Object.defineProperty(Object.prototype, 'isEmpty', {
get() {
for(var p in this) {
if (this.hasOwnProperty(p)) {return false}
}
return true;
}
});
let users = {};
let colors = {primary: 'red'};
let sizes = {sm: 100, md: 200, lg: 300};
console.log(
'\nusers =', users,
'\nusers.isEmpty ==> ' + users.isEmpty,
'\n\n-------------\n',
'\ncolors =', colors,
'\ncolors.isEmpty ==> ' + colors.isEmpty,
'\n\n-------------\n',
'\nsizes =', sizes,
'\nsizes.isEmpty ==> ' + sizes.isEmpty,
'\n',
''
);
It's weird that I haven't encountered a solution that compares the object's values as opposed to the existence of any entry (maybe I missed it among the many given solutions).
I would like to cover the case where an object is considered empty if all its values are undefined:
const isObjectEmpty = obj => Object.values(obj).every(val => typeof val === "undefined")
console.log(isObjectEmpty({})) // true
console.log(isObjectEmpty({ foo: undefined, bar: undefined })) // true
console.log(isObjectEmpty({ foo: false, bar: null })) // false
Example usage
Let's say, for the sake of example, you have a function (paintOnCanvas) that destructs values from its argument (x, y and size). If all of them are undefined, they are to be left out of the resulting set of options. If not they are not, all of them are included.
function paintOnCanvas ({ brush, x, y, size }) {
const baseOptions = { brush }
const areaOptions = { x, y, size }
const options = isObjectEmpty(areaOptions) ? baseOptions : { ...baseOptions, areaOptions }
// ...
}

RxJs channing, setting and reading external values

I'm new in rxjs world and I have to rewrite some code. So, I draft my ideas.
I have a request, which could fail and return an observable. I simulate that with the ob-variable and two map operations. Then, I try to catch an error. I need the result in my local variable selected and raise an event on isChanged. I call my function now via subscription. I don't need a result.
My question: Is one big pipe enough and can I use following approach for the work with my local variables?
import { of, map, Observable, tap, Subject, throwError, EMPTY } from 'rxjs';
import { catchError } from 'rxjs/operators';
let selected = 0;
const isChanged = new Subject<number>();
function myfunc(): Observable<boolean> {
const ob = of(1,3,4,5,7);
return ob.pipe(
// simulates a http request
map(v => v*2),
// simulates a rare error condition
map(v => {
// if (v === 8) { throw `four`; }
if (v === 10) { throw `ten`; }
return v;
}),
// play with different failure situations
catchError((e) => {
if (e === `four`) {
return of(4);
}
if (e === `ten`) {
return EMPTY;
}
console.warn(e);
return throwError(e);
}
),
// I need the result in a local variable
// I need a information about success
// I need the result not really
map((res) => {
selected = res;
isChanged.next(res);
return true;
})
);
}
console.log(`a: selected is ${selected}`);
isChanged.subscribe(v =>
console.log(`b: isChanged received: ${v}, selected is ${selected}`));
console.log(`c: selected is ${selected}`);
// I have to call the function
myfunc().subscribe((b) => {
console.log(`d: selected is ${selected}`);
});
I create the world in Stackblitz too:
https://stackblitz.com/edit/rxjs-6fgggh?devtoolsheight=66&file=index.ts
I see results like expected. But I'm not sure if all ideas are the right way to solve all problems.
Thanks for you thought.

Operator that skips the next emission from the source whenever another Observable emits

I have a use case where I need an Observable to skip its next emission whenever another notifier Observable emits.
source: |---X---X---X---X---X---X---X---X---X---X--|>
notifier: |-------------X---------X----------X-------|>
result: |---X---X---X-------X---X-------X-------X--|>
Basically, I want an operator called skipNextWhen that takes in the notifier observable and skips the next emission from the source.
I tried using an implementation that uses the pausable operator (re-implemented using switchMap), but couldn't get it to work.
pausable.ts
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/observable/never';
import 'rxjs/add/operator/startWith';
declare module 'rxjs/Observable' {
interface Observable<T> {
pausable: typeof pausable;
}
}
function pausable<T>(notifier: Observable<boolean>): Observable<T> {
return notifier.startWith(false).switchMap((paused) => {
if (paused) {
return Observable.never();
} else {
const source = new Subject();
this.subscribe(source);
return source;
}
});
}
Observable.prototype.pausable = pausable;
skipNextWhen.ts
import { Observable } from 'rxjs/Observable';
import './pausable';
declare module 'rxjs/Observable' {
interface Observable<T> {
skipNextWhen: typeof skipNextWhen;
}
}
function skipNextWhen<T, R>(other: Observable<T>): Observable<R> {
const notifier = Observable.merge(this.map(() => false),
other.map(() => true));
return this.pausable(notifier);
}
Observable.prototype.skipNextWhen = skipNextWhen;
Is there a more suitable operator that I should consider using instead? The behavior I'm seeing with my current implementation is that the result Observable emits once, and then never again - even if the notifier Observable never emits.
I can think of two solutions to this:
Using .filter(), .do() and a few side-effects.
This is mayne easier to understand solution even though it's not that "Rx" way:
function skipNextWhen(other) {
let skipNext = false;
return this.merge(other.do(() => skipNext = true).filter(() => false))
.filter(val => {
const doSkip = skipNext;
skipNext = false;
return !doSkip;
});
}
I'm using merge() just to update skipNext, other's value is always ignored.
Using .scan():
This solution is without any state variables and side-effects.
function skipNextWhen(other) {
const SKIP = 'skip';
return this.merge(other.mapTo(SKIP))
.scan((acc, val) => {
if (acc === SKIP) {
return null;
} else if (val === SKIP) {
return SKIP;
} else {
return val;
}
}, [])
.filter(val => Boolean(val) && val !== SKIP);
}
Basically, when SKIP arrives I return it right away because it's going to be passed again in acc parameter by the scan() operator and later ignored by filter().
If I receive a normal value but the previous value was SKIP I ignore it and return just null which is later filter away.
Both solutions give the same result:
Observable.prototype.skipNextWhen = skipNextWhen;
const source = Observable.range(1, 10)
.concatMap(val => Observable.of(val).delay(100));
source
.skipNextWhen(Observable.interval(350))
.subscribe(console.log);
This prints the following:
1
2
3
5
6
8
9
10
Just be aware that you're not in fact creating new operator. You just have a shortcut for an operator chain. This for example doesn't let you unsubscribe from other when the source completes.
I've started a (very) small library of some rxjs utils I've wanted. It happens to have a function to do exactly what you ask: skipAfter. From the docs:
source: -1-----2-----3-----4-----5-|
skip$: ----0----------0-0----------
result: -1-----------3-----------5-|
The library is here: https://github.com/simontonsoftware/s-rxjs-utils

Async binding in Aurelia

I'm trying to bind an async value to one of my Aurelia templates, and obviously all I get is [object Promise] in return.
I found this article http://www.sobell.net/aurelia-async-bindings/ which excellently explains how to solve this problem using a binding behavior which looks like this:
// http://www.sobell.net/aurelia-async-bindings/
export class asyncBindingBehavior {
bind (binding, source) {
binding.originalUpdateTarget = binding.updateTarget;
binding.updateTarget = a => {
if (typeof a.then === 'function') {
binding.originalUpdateTarget('...');
a.then(d => {
binding.originalUpdateTarget(d);
});
}
else {
binding.originalUpdateTarget(a);
}
};
}
unbind (binding) {
binding.updateTarget = binding.originalUpdateTarget;
binding.originalUpdateTarget = null;
}
}
This works perfectly when the promise resolves with a string or other non-object-like variable.
But what if my promise resolves with an object? How would I go about accessing the property I need inside that object?
Because if I do: ${object.property & async} inside my template then it will fail as object.property isn't a promise - only object is.
I added a bit of a hack that allows me to specify a property as an argument to async, like this: ${object & async:'property'} and updated my binding behavior as such:
// http://www.sobell.net/aurelia-async-bindings/
export class asyncBindingBehavior {
bind (binding, source, property) {
binding.originalUpdateTarget = binding.updateTarget;
binding.updateTarget = a => {
if (typeof a.then === 'function') {
binding.originalUpdateTarget('...');
a.then(d => {
if (property) {
binding.originalUpdateTarget(d[property]);
}
else {
binding.originalUpdateTarget(d);
}
});
}
else {
binding.originalUpdateTarget(a);
}
};
}
unbind (binding) {
binding.updateTarget = binding.originalUpdateTarget;
binding.originalUpdateTarget = null;
}
}
But this feels very much like a hack to me, and it also won't allow me to access any deeper properties like object.parent.child.
I also found this (rather old) issue on GitHub: https://github.com/aurelia/templating/issues/81 where they use a getValue method. I've never heard of this method and trying to use it fails so I'm not sure how that works at all...
Any ideas?
You could sidestep your conundrum by specifying a function as the third parameter, giving the flexibility to do much more than simple property extraction.
You could write something like this :
export class asyncBindingBehavior {
bind (binding, source, transformer="default") {
binding.originalUpdateTarget = binding.updateTarget;
binding.updateTarget = a => {
if (typeof a.then === 'function') {
binding.originalUpdateTarget('...');
a.then(d => binding.originalUpdateTarget(transformFunctions[transformer](d)));
} else {
binding.originalUpdateTarget(a);
}
};
}
unbind (binding) {
binding.updateTarget = binding.originalUpdateTarget;
binding.originalUpdateTarget = null;
}
}
The transformFunctions lookup would be necessary(?) due to the way Aurelia bindings are specified as HTML-ebbedded or template directives (ie all params must be String). Unless Aurelia offers a better way better way to "pass a function" (Value Converters?), you would write something like this :
export var transformFunctions = {
default: (d) => d,
transform1: (d) => d.someProperty,
transform2: (d) => d.someProperty.someOtherProperty,
transform3: someFunction,
transform4: someOtherFunction.bind(null, someData);
}
Of course, you would give the functions better names.

SCRIPT5007: Unable to get value of the property 'indexOf': object is null or undefined.Please help to solve this

I am posting full code now please check and let me know what i have to modify in this code to solve this problem in IE:
var values = [];
$("#tblitem #itm").each(function(a, b)
{
values[a] = b.text;
});
valuex[x] is used to fetch itemname here.and below i used it in indexof().indexof() is working well before i use array.problem occurs after the use of array only in IE.
var compare_value_oldd="$500";
var compare_value_neww=parseFloat(compare_value_oldd.replace(/[^0-9-.]/g,''));
for( var x in values)
{
if (parseFloat(totalnumm.replace(/[^0-9-.]/g,'')) > compare_value_neww && values[x].indexOf("Custom") > -1 )
{
if ($.cookie('test_status1') != '2')
{
$('#element_to_pop_up1').bPopup({
content: 'image', //'ajax', 'iframe' or 'image'
contentContainer: '.content',
loadUrl: 'coupon.jpg'
});
<!--cookie settings here-->
<!--expire time of cookie is 30 days.you can change it as per your requirements-->
$.cookie('test_status1', '2', { expires: 30 });
}
}
}
I got error in this line.
**if (parseFloat(totalnumm.replace(/[^0-9-.]/g,'')) > compare_value_neww && values[x].indexOf("Custom") > -1 )**
You should wrap element inside jquery object:
var values = [];
$("#tblitem #itm").each(function(a, b)
{
values[a] = $(b).text();
});
I don't know which kind of element is '#itm', you could have to use $(b).html(); or $(b).val();

Resources