I have the code below and I need to know how I could use spyon with previousValue and currentValue in my test to coverage the conditional if (cur !== prev && cur === 100).
ngOnChanges(changes: SimpleChanges) {
if (changes['highlightData'] && !changes['highlightData'].isFirstChange()) {
const prev: any = changes['highlightData'].previousValue;
const cur: any = changes['highlightData'].currentValue;
if (cur !== prev && cur === 100) {
this._render.setElementClass(this._elementRef.nativeElement, 'animate', true);
setTimeout(() => {
this._render.setElementClass(this._elementRef.nativeElement, 'animate', false);
}, 3000);
}
}
}
Does anyone know how can I do that?
Thanks.
2 methods are provided in this blog, one is to manually call it and other is to use a wrapper to trigger it by framework
Related
I use ag-grid table - I am grouping the columns e.g. like:
Is it possible to set columns expanded the same way they were after components reload?
How to save how columns were expanded and then reload it?
One way is to store the ids of the nodes which are expanded (I do so in local storage as there aren't many rows in my table and I know I won't store anything confidential). Then on reload, retrieve the nodes that should be expanded and expand them:
<ag-grid-angular
(rowGroupOpened)="onRowGroupOpened()"
(gridReady)="onGridReady($event)">
</ag-grid-angular>
localStorageKey = 'storage-key-name';
onRowGroupOpened(): void {
let allExpanded = true;
const expandedNodeDetails: string[] = [];
if (this.myGrid.gridApi != null) {
this.myGrid.gridApi.forEachNode(node => {
if (node.group || (node.allChildrenCount > 0)) {
if (!this.restoringExpandedNodes) {
expandedNodeDetails.push(node.key);
}
}
});
}
if (!this.restoringExpandedNodes) {
localStorage.setItem(this.localStorageKey, JSON.stringify(expandedNodeDetails));
}
}
onGridReady(): void {
this.restoreExpandedNodes();
}
restoreExpandedNodes(): void {
const itemsInStorage = JSON.parse(localStorage.getItem(this.localStorageKey));
if ((itemsInStorage != null) && (this.myGrid != null) && (this.myGrid.gridApi != null)) {
this.restoringExpandedNodes = true;
this.myGrid.gridApi.forEachNode(node => {
if (node.group || (node.allChildrenCount > 0)) {
const expandedDetails = this.getExpandedDetails(node, null);
const index = itemsInStorage.findIndex(storageItem => storageItem === expandedDetails);
if (index !== -1) {
node.expanded = true;
} else if ((itemToSelect != null) && (node.key == itemToSelect.ItemFullName)) {
node.expanded = true;
}
}
});
this.myGrid.gridApi.onGroupExpandedOrCollapsed();
this.restoringExpandedNodes = false;
}
}
I've had to sanitise this code so please let me know if something doesn't make sense
const interval = setInterval(() => {
fire.database().ref().child(getpath())
.once("value",
(snapshot) => {
let item = snapshot.val()
console.log(item)
if (item !== null) {
let array = [];
Object.
keys(item)
.forEach(i => array.push(item[i]));
setCard1(array);
}
console.log(item, "item")
if (item !== null) {
itemlen = 7 //length of object I get from valid result
//stop polling for results
console.log(itemlen, "should clear")
}
else {
console.log("polling")
}
})
}, 1000)
console.log("comingout")
if (itemlen !== 0) {
console.log("goingIn")
clearInterval(interval);
}
}, [prefVar]);
expected clearinterval to stop the setinterval function but it is running continuosly and not stopping
itemlen is getting non zero values.Is there a better way of implementing this ?
I want stop useEffect once I get valid value from db.My code inside the for setinterval selects a random path and retrieve that path only problem is that sometimes the path is empty,thus using setInterval
I would create two state items, one which keeps the interval and the other which stores itemlen, and would use another useEffect to listen on changes to itemlen, and when it is not 0, the interval should clear. Also, I would check if there is another interval running before you start another one.
const [itemlen, setItemlen] = useState(0);
const [pollingInterval, setPollingInterval] = useState(null);
useEffect(() => {
if (pollingInterval === null) {
setPollingInterval(setInterval(() => {
fire.database().ref().child(getpath())
.once("value",
(snapshot) => {
let item = snapshot.val()
console.log(item)
if (item !== null) {
let array = [];
Object.
keys(item)
.forEach(i => array.push(item[i]));
setCard1(array);
}
console.log(item, "item")
if (item !== null) {
setItemlen(7);
console.log("should clear")
} else {
console.log("polling")
}
})
}, 1000));
}
}, [prefVar]);
useEffect(() => {
if (itemlen !== 0 && pollingInterval !== null) {
clearInterval(pollingInterval);
setPollingInterval(null);
}
}, [itemlen])
Steps to reproduce
The recurrence link is this: https://stackblitz.com/edit/typescript-vuejs-element-3kko7a
password input 2
username input 11
Change username to 2// should be able to submit, but not
Expected: formvalid = true
Validate Code here:
checkForm() {
// console.log('validate runs');
// #ts-ignore
const fields = this.$refs.ruleForm.fields;
if (fields.find((f) => f.validateState === 'validating')) {
setTimeout(() => {
this.checkForm();
}, 100);
}
this.formValid = fields.reduce((acc, f) => {
const valid = (f.isRequired && f.validateState === 'success');
const notErroring = (!f.isRequired && f.validateState !== 'error');
return acc && (valid || notErroring);
}, true);
console.log('valid:', this.$data.formValid);
}
Basically you watch ruleForm - so everytime ruleForm changes you trigger checkform - but your validtor triggers on blur after you set ruleForm so you first test then turn valid. change this into a getter:
get formValid(){
const fields = this.$refs.ruleForm.fields || [];
if (fields.find((f) => f.validateState === 'validating')) {
setTimeout(() => {
this.checkForm();
}, 100);
}
return fields.reduce((acc, f) => {
const valid = (f.isRequired && f.validateState === 'success');
const notErroring = (!f.isRequired && f.validateState !== 'error');
return acc && (valid || notErroring);
}, fields.length > 0);
}
I want to inherit function add_product of models.Order.
Here is the original function
/point_of_sale/static/src/js/models.js
add_product: function(product, options){
if(this._printed){
this.destroy();
return this.pos.get_order().add_product(product, options);
}
this.assert_editable();
options = options || {};
var attr = JSON.parse(JSON.stringify(product));
attr.pos = this.pos;
attr.order = this;
var line = new exports.Orderline({}, {pos: this.pos, order: this, product: product});
if(options.quantity !== undefined){
line.set_quantity(options.quantity);
}
if(options.price !== undefined){
line.set_unit_price(options.price);
}
//To substract from the unit price the included taxes mapped by the fiscal position
this.fix_tax_included_price(line);
if(options.discount !== undefined){
line.set_discount(options.discount);
}
if(options.extras !== undefined){
for (var prop in options.extras) {
line[prop] = options.extras[prop];
}
}
var to_merge_orderline;
for (var i = 0; i < this.orderlines.length; i++) {
if(this.orderlines.at(i).can_be_merged_with(line) && options.merge !== false){
to_merge_orderline = this.orderlines.at(i);
}
}
if (to_merge_orderline){
to_merge_orderline.merge(line);
} else {
this.orderlines.add(line);
}
this.select_orderline(this.get_last_orderline());
if(line.has_product_lot){
this.display_lot_popup();
}
},
I need to add one more condidtion like,
if(options.is_promo !== undefined){
line.set_promo(options.is_promo);
}
},
So in my custom module, I tried this,
var _super_order = models.Order.prototype;
models.Order = models.Order.extend({
add_product: function(product, options){
if(options.is_promo !== undefined){
line.set_promo(options.is_promo);
}
_super_order.add_product.apply(this,arguments);
},
But it throws an error, line is not defined.
How can i do it?
If I have like 10 m.module on my page, can I call m.startComputation, m.endComputation, m.redraw or m.request for only one of those modules?
It looks like any of these will redraw all of my modules.
I know only module 1 will be affected by some piece of code, I only want mithril to redraw that.
Right now, there's no simple support for multi-tenancy (i.e. running multiple modules independently of each other).
The workaround would involve using subtree directives to prevent redraws on other modules, e.g.
//helpers
var target
function tenant(id, module) {
return {
controller: module.controller,
view: function(ctrl) {
return target == id ? module.view(ctrl) : {subtree: "retain"}
}
}
}
function local(id, callback) {
return function(e) {
target = id
callback.call(this, e)
}
}
//a module
var MyModule = {
controller: function() {
this.doStuff = function() {alert(1)}
},
view: function() {
return m("button[type=button]", {
onclick: local("MyModule", ctrl.doStuff)
}, "redraw only MyModule")
}
}
//init
m.module(element, tenant("MyModule", MyModule))
You could probably also use something like this or this to automate decorating of event handlers w/ local
Need multi-tenancy support for components ? Here is my gist link
var z = (function (){
//helpers
var cache = {};
var target;
var type = {}.toString;
var tenant=function(componentName, component) {
return {
controller: component.controller,
view: function(ctrl) {
var args=[];
if (arguments.length > 1) args = args.concat([].slice.call(arguments, 1))
if((type.call(target) === '[object Array]' && target.indexOf(componentName) > -1) || target === componentName || target === "all")
return component.view.apply(component, args.length ? [ctrl].concat(args) : [ctrl])
else
return {subtree: "retain"}
}
}
}
return {
withTarget:function(components, callback) {
return function(e) {
target = components;
callback.call(this, e)
}
},
component:function(componentName,component){
//target = componentName;
var args=[];
if (arguments.length > 2) args = args.concat([].slice.call(arguments, 2))
return m.component.apply(undefined,[tenant(componentName,component)].concat(args));
},
setTarget:function(targets){
target = targets;
},
bindOnce:function(componentName,viewName,view) {
if(cache[componentName] === undefined) {
cache[componentName] = {};
}
if (cache[componentName][viewName] === undefined) {
cache[componentName][viewName] = true
return view()
}
else return {subtree: "retain"}
},
removeCache:function(componentName){
delete cache[componentName]
}
}
})();