TypeScript/Angular: Cannot find name 'XXX' - function

I have two functions in the same TypeScript component. When I try to call one already declared, VSCode reports that it "[ts] Cannot find name 'XXX'.".
As requested by Tiep Phan, this is the full code:
liveSearchFMs(input: any) {
this._ectmService.getFMsFromUserSearch(input).subscribe(
fanmissions => this.fanmissions = fanmissions,
error => this.errorMessage = <any>error
);
}
timeout(input) {
var enteredValue = input;
var timeout = null;
clearTimeout(timeout);
timeout = setTimeout(function () {
this.liveSearchFMs(enteredValue);
}, 1000);
}

I guess you wanna create something like this
export class EctmListComponent implements OnInit {
// other code
private timeoutTracker;
timeout(input) {
if (this.timeoutTracker) {
clearTimeout(this.timeoutTracker);
}
//use arrow function instead
this.timeoutTracker = setTimeout(() => {
this.liveSearchFMs(input);
}, 1000);
// or store context first
/*
const ctx = this;
this.timeoutTracker = setTimeout(function() {
ctx.liveSearchFMs(input);
}, 1000);
*/
// or using bind method
/*
this.timeoutTracker = setTimeout((function() {
this.liveSearchFMs(input);
}).bind(this), 1000);
*/
}
}

You need to use this keyword. so this.liveSearchFMs

Related

Merge mixin in vue

I'm working in vue/quasar application.
I've my mixin like this in my view.cshtml
var mixin1 = {
data: function () {
return { data1:0,data2:'' }
}
,
beforeCreate: async function () {
...}
},
methods: {
addformulaire(url) {
},
Kilometrique() { }
}
}
And I want merge with my content in js file (it's to centralize same action an severals cshtml)
const nomeMixins = {
data: function () {
return { loadingcdt: false, lstclt: [], filterclient: [], loadingdoc: false, lstdoc: [], filterdoc: [] }
},
computed: {
libmntpiece(v) { return "toto"; }
},
methods: {
findinfcomplemtX3(cdecltx3, cdedocx3) {
},
preremplissagex3: async function (cdecltx3, cdedocx3) {
}
}
}
};
I want merge this 2 miwin in one. But when I try assign or var mixin = { ...mixin1, ...nomeMixins };
I've only mixin1 nothing about methods,data from my js file nomeMixins but merging failed cause I've same key in my json object. I'm trying to make a foreach but failed too
Someone try to merge to mixin / json object with same key in the case you've no double child property ?
You cant merge mixins in that way. the spread syntax will overwrite keys e.g data, computed, methods etc and final result will not be suitable for your purpose.
refer documentation for adding mixins in your component. Also note that You can easily add multiple mixins in any component, so I don't think combination of two mixins will be any useful.
UPDATE
reply to YannickIngenierie answer and pointing out mistakes in this article
Global Mixins are not declared like this
// not global mixin; on contrary MyMixin is local
// and only available in one component.
new Vue({
el: '#demo',
mixins: [MyMixin]
});
Local Mixins are not declared like this
// NOT local mixin; on contrary its global Mixin
// and available to all components
const DataLoader = Vue.mixin({....}}
Vue.component("article-card", {
mixins: [DataLoader], // no need of this
template: "#article-card-template",
created() {
this.load("https://jsonplaceholder.typicode.com/posts/1")
}
});
Point is refer documentation first before reading any article written by some random guy, including me. Do slight comparison what he is saying whats in documentation.
After working and searching... I find this one And understand that I can add directly mixin in my compoment (don't laught I'm begging with vue few months ago)
my custommiwin.js
const DataLoader = Vue.mixin({
data: function () {
return { loadingcdt: false, lstclt: [], filterclient: [], loadingdoc: false, lstdoc: [], filterdoc: [] }
},
methods: {
filterClt: async function (val, update, abort) {
if (val.length < 3) { abort(); return; }
else {//recherche
this.loadingcdt = true;
let res = await axios...
this.loadingcdt = false;
}
update(() => {
const needle = val.toLowerCase();
this.filterclient = this.lstclt.filter(v => v.libelle.toLowerCase().indexOf(needle) > -1 || v.id.toLowerCase().indexOf(needle) > -1);
})
},
filterDocument: async function (val, update, abort, cdecltx3) {
if (!cdecltx3 || val.length < 3) { abort(); return; }
else {//recherche
this.loadingdoc = true;
let res = await axios({ ...) }
this.loadingdoc = false;
}
update(() => {
const needle = val.toLowerCase();
this.filterdoc = this.lstdoc.filter(v => v.id.toLowerCase().indexOf(needle) > -1);
})
},
}
});
and in my compoment.js I add this
mixins: [DataLoader],
I include all my js file in my cshtml file

how to add AngularJS DHTML directive?

dhtml syntax help
this is the syntax used
I do not exhaust the complete dhtmlXGrid API here...
however configure and dataLoaded callbacks let user
add any additional configuration they desire
"use strict";
angular.module('dhxDirectives')
.directive('dhxGrid', function factory(DhxUtils) {
return {
restrict: 'E',
require: 'dhxGrid',
controller: function () {
},
scope: {
/**
* Grid will be accessible in controller via this scope entry
* after it's initialized.
* NOTE: For better design and testability you should use instead the
* configure and dataLoaded callbacks.
*/
dhxObj: '=',
/** Mandatory in current implementation! */
dhxMaxHeight: '=',
/** Optional. Default is 100%. */
dhxMaxWidth: '=',
/**
* Data is given here as an object. Not a filename! Must conform to the
* specified or default dataFormat
*/
dhxData: '=',
/**
* View possible formats here: http://docs.dhtmlx.com/grid__data_formats.html
* Currently supported:
* ['Basic JSON', 'Native JSON'] // 'Basic JSON' is default value
*/
dhxDataFormat: '=',
/** Optional! Recommended! http://docs.dhtmlx.com/api__dhtmlxgrid_setheader.html */
dhxHeader: '=',
/** Optional! http://docs.dhtmlx.com/api__dhtmlxgrid_setcoltypes.html */
dhxColTypes: '=',
/** Optional! http://docs.dhtmlx.com/api__dhtmlxgrid_setcolsorting.html */
dhxColSorting: '=',
/** Optional! http://docs.dhtmlx.com/api__dhtmlxgrid_setcolalign.html */
dhxColAlign: '=',
/** Optional! http://docs.dhtmlx.com/api__dhtmlxgrid_setinitwidthsp.html */
dhxInitWidths: '=',
/** Optional! http://docs.dhtmlx.com/api__dhtmlxgrid_setinitwidths.html */
dhxInitWidthsP: '=',
/**
* preLoad and postLoad callbacks to controller for additional
* customization power.
*/
dhxConfigureFunc: '=',
dhxOnDataLoaded: '=',
/**
* [{type: <handlerType>, handler: <handlerFunc>}]
* where type is 'onSomeEvent'
* Events can be seen at: http://docs.dhtmlx.com/api__refs__dhtmlxgrid_events.html
* Optional
*/
dhxHandlers: '=',
dhxVersionId: '=',
dhxContextMenu: '='
},
compile: function compile(/*tElement, tAttrs, transclude*/) {
return function (scope, element/*, attrs*/) {
var loadStructure = function () {
$(element).empty();
$('<div></div>').appendTo(element[0]);
var rootElem = element.children().first();
var width = scope.dhxMaxWidth ? (scope.dhxMaxWidth + 'px') : '100%';
var height = scope.dhxMaxHeight ? (scope.dhxMaxHeight + 'px') : '100%';
rootElem.css('width', width);
rootElem.css('height', height);
//noinspection JSPotentiallyInvalidConstructorUsage
if (scope.dhxObj) {
DhxUtils.dhxDestroy(scope.dhxObj);
}
scope.dhxObj = new dhtmlXGridObject(rootElem[0]);
var grid = scope.dhxObj;
grid.setImagePath(DhxUtils.getImagePath());
grid.enableAutoHeight(!!scope.dhxMaxHeight, scope.dhxMaxHeight, true);
grid.enableAutoWidth(!!scope.dhxMaxWidth, scope.dhxMaxWidth, true);
scope.dhxContextMenu ? grid.enableContextMenu(scope.dhxContextMenu) : '';
scope.$watch(
"dhxContextMenu",
function handle( newValue, oldValue ) {
grid.enableContextMenu(newValue);
}
);
scope.dhxHeader ? grid.setHeader(scope.dhxHeader): '';
scope.dhxColTypes ? grid.setColTypes(scope.dhxColTypes): '';
scope.dhxColSorting ? grid.setColSorting(scope.dhxColSorting): '';
scope.dhxColAlign ? grid.setColAlign(scope.dhxColAlign): '';
scope.dhxInitWidths ? grid.setInitWidths(scope.dhxInitWidths): '';
scope.dhxInitWidthsP ? grid.setInitWidthsP(scope.dhxInitWidthsP): '';
// Letting controller add configurations before data is parsed
if (scope.dhxConfigureFunc) {
scope.dhxConfigureFunc(grid);
}
grid.init();
// Finally parsing data
var dhxDataFormat = scope.dhxDataFormat || 'Basic JSON';
switch (dhxDataFormat) {
case 'Basic JSON':
grid.parse(scope.dhxData, 'json');
break;
case 'Native JSON':
grid.load(scope.dhxData, 'js');
break;
}
// Letting controller do data manipulation after data has been loaded
if (scope.dhxOnDataLoaded) {
scope.dhxOnDataLoaded(grid);
}
DhxUtils.attachDhxHandlers(grid, scope.dhxHandlers);
DhxUtils.dhxUnloadOnScopeDestroy(scope, grid);
};
scope.$watch('dhxVersionId', function (/*newVal, oldVal*/) {
console.log('rebuilding...');
loadStructure();
});
}
}
};
});
© 2020 GitHub, Inc.
I do not exhaust the complete dhtmlXGrid API here...
however configure and dataLoaded callbacks let user
add any additional configuration they desire
<dhx-grid
dhx-obj="grid.obj"
style="height: 100%"
dhx-data="gridData"
dhx-col-sorting="'str,str,int'"
dhx-header="'Title,Author,Copies sold'"
dhx-context-menu="contextMenu"
dhx-handlers="grid.handlers"></dhx-grid>
angular.module('myApp')
.controller('GridController', ['$scope' ,function ($scope) {
$scope.grid = {
obj: {},
handlers: [
{type: "onRowSelect", handler: function (id) {
$scope.grid.obj.deleteRow(id);
}}
]
};
$scope.alert = function alert(event_name) {
switch (event_name) {
case "refreshsize":
$scope.grid.obj.setSizes();
}
};
$scope.contextMenu = {};
$scope.gridData = {
rows:[
{ id:1, data: ["Click a row", "John Grasham", "100"]},
{ id:2, data: ["to have it", "Stephen Pink", "2000"]},
{ id:3, data: ["deleted", "Terry Brattchet", "3000"]},
{ id:4, data: ["La la la", "Isaac Zimov", "4000"]},
{ id:5, data: ["La la la", "Sax Pear", "5000"]}
]
};
}]);
"use strict";
/**
* Created by Emanuil on 01/02/2016.
*/
angular.module('dhxDirectives')
.factory('DhxUtils', [function () {
var _imgPath = "bower_components/dhtmlx/imgs/";
/**
* #param dhxObject
* #param dhxHandlers
*/
var attachDhxHandlers = function (dhxObject, dhxHandlers) {
(dhxHandlers || [])
.forEach(function (info) {
dhxObject.attachEvent(info.type, info.handler);
});
};
var getImagePath = function () {
return _imgPath;
};
var setImagePath = function (imgPath) {
_imgPath = imgPath;
};
/**
* I hope to never resort to using that
*/
var createCounter = function () {
var current = -1;
return function () {
current++;
return current;
};
};
var removeUndefinedProps = function(obj) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop) && obj[prop] === undefined) {
delete obj[prop];
}
}
};
var dhxDestroy = function (dhxObj) {
var destructorName =
'destructor' in dhxObj
? 'destructor'
:
('unload' in dhxObj
? 'unload'
: null);
if (destructorName === null) {
console.error('Dhtmlx object does not have a destructor or unload method! Failed to register with scope destructor!');
return;
}
dhxObj[destructorName]();
};
var dhxUnloadOnScopeDestroy = function (scope, dhxObj) {
var destructorName =
'destructor' in dhxObj
? 'destructor'
:
('unload' in dhxObj
? 'unload'
: null);
if (destructorName === null) {
console.error('Dhtmlx object does not have a destructor or unload method! Failed to register with scope destructor!');
return;
}
scope.$on(
"$destroy",
function (/*event*/) {
dhxObj[destructorName]();
}
);
};
return {
attachDhxHandlers: attachDhxHandlers,
getImagePath: getImagePath,
setImagePath: setImagePath,
createCounter: createCounter,
removeUndefinedProps: removeUndefinedProps,
dhxUnloadOnScopeDestroy: dhxUnloadOnScopeDestroy,
dhxDestroy: dhxDestroy
};
}]);

Setting data in viewModel knockoutjs from html5 websocket

I am trying to create knockout.js component that is getting data from HTML5 Websocket. Websocket code is in separate script e.g. util.js. I am able to connect and get data from socket, but dont know how correctly to set corresponding property in component`s ViewModel.
Websocket - util.js:
var options = {
server: '127.0.0.1',
port: '12345'
};
var socket, loadedFlag;
var timeout = 2000;
var clearTimer = -1;
var data = {};
function handleErrors(sError, sURL, iLine)
{
return true;
};
function getSocketState()
{
return (socket != null) ? socket.readyState : 0;
}
function onMessage(e)
{
data=$.parseJSON(e.data);
// ???? Is it possible to have here something like
// ???? viewModel.getDataWS1(data);
}
function onError()
{
clearInterval(clearTimer);
socket.onclose = function () {
loadedFlag = false;
};
clearTimer = setInterval("connectWebSocket()", timeout);
}
function onClose()
{
loadedFlag = false;
clearInterval(clearTimer);
clearTimer = setInterval("connectWebSocket()", timeout);
}
function onOpen()
{
clearInterval(clearTimer);
console.log("open" + getSocketState());
}
function connectWebSocket()
{
if ("WebSocket" in window)
{
if (getSocketState() === 1)
{
socket.onopen = onOpen;
clearInterval(clearTimer);
console.log(getSocketState());
}
else
{
try
{
host = "ws://" + options.server + ":" + options.port;
socket = new WebSocket(host);
socket.onopen = onOpen;
socket.onmessage = function (e) {
onMessage(e);
};
socket.onerror = onError;
socket.onclose = onClose;
}
catch (exeption)
{
console.log(exeption);
}
}
}
}
Component (productDisplay.js) - creating so that is can be used on multiple pages:
define([
'jquery',
'app/models/productDisplayModel',
'knockout',
'mapping',
'socket'
],
function ($, model, ko, mapping) {
ko.components.register('product', {
viewModel: {require: 'app/models/productModel'},
template: {require: 'text!app/views/product.html'}
});
});
Product ViewModel (productModel.js) - where I struggle to set viewModel property to data from websocket:
var viewModel = {};
define(['knockout', 'mapping', 'jquery'], function (ko, mapping, $) {
function Product(name, rating) {
this.name = name;
this.userRating = ko.observable(rating || null);
}
function MyViewModel() {
this.products = ko.observableArray(); // Start empty
}
MyViewModel.prototype.getDataWS1 = function () {
//Websocket has not connected and returned data yet, so data object is empty
// ???? Is there anyway I can add something like promise so that the value is set once socket is connected?
this.products(data);
};
// apply binding on page load
$(document).ready(function () {
connectToServer1();
viewModel = new MyViewModel();
ko.applyBindings(viewModel);
viewModel.getDataWS1();
});
});
Thank you for any ideas.
You can update an observable when you get a message in the following manner:
util.js
function onMessage(e) {
var productData = $.parseJSON(e.data);
viewModel.addNewProduct(productData);
}
productModel.js
function Product(name, rating) {
this.name = name;
this.userRating = ko.observable(rating || null);
}
function MyViewModel() {
this.products = ko.observableArray(); // Start empty
}
MyViewModel.prototype.addNewProduct(product) {
var newProduct = new Product(product.name, product.rating);
this.products.push(newProduct);
}
Basically the idea is that when you get a message (in onMessage function), you will parse the data and call a function in your viewmodel to add the message data to the viewmodel properties (observables, observableArrays, etc.)

Aurelia update value of bound item in another class

I guess the question boils down how to i pass the instance of a property to another class.
I have something like this:
import timerClass from "./timer";
export class App {
constructor() {
this.timeLeft = 6; //<--- I want to update this
new timerClass(this.timeLeft);
}
activate() {
}
}
and
export default class {
constructor(time) {
this.initialTime = time;
setInterval(function () {
if (--time < 0) {
time = this.initialTime; //<--- From here
}
}, 1000);
}
}
Time is passed in but not reflected in the view when updated.
In knockout this was easy as all observables are functions an I could pass it round all over the place. How would i do the same here, should I wrap it in a function too?
When you call
new timerClass(this.timeLeft);
you pass your variable by value, i.e. the timer just gets 6 and there is no way to modify it there. The easiest way to fix this is indeed pass the callback function. I made it work with the following code.
timer.js:
export default class {
constructor(time, callback) {
this.initialTime = time;
this.currentTime = time;
setInterval(() => {
if (--this.currentTime < 0) {
this.currentTime = this.initialTime;
}
callback(this.currentTime);
}, 1000);
}
}
app.js:
constructor(){
this.timeLeft = 6;
var timer = new timerClass(this.timeLeft, v => this.timeLeft = v);
}
So I did some more reading and came across the aurelia-event-aggregator
http://aurelia.io/docs#the-event-aggregator
This allowed me to try a different angle. As my timer is eventually going to become a game loop this pub/sub way of doing it will work quite nicely.
Im still quite green with the syntax so I imagine its doing some things not entirely "best practice" but hope it helps someone.
main.js
import {inject} from 'aurelia-framework';
import {EventAggregator} from 'aurelia-event-aggregator';
import TimerClass from "./timer";
#inject(EventAggregator)
export class Main {
constructor(eventAggregator) {
this.eventAggregator = eventAggregator;
this.timer = new TimerClass(this.eventAggregator);
this.eventAggregator.subscribe('gameLoop', currentTime => {
this.timeLeft = currentTime
});
}
activate() {
this.timer.start();
}
}
timer.js
export default class Timer {
constructor(eventAggregator) {
this.eventAggregator = eventAggregator;
}
start(){
var initalTime = 5;
var currentTime = initalTime;
setInterval(() => {
if (--currentTime < 0) {
currentTime = initalTime;
}
this.eventAggregator.publish('gameLoop', currentTime);
}, 500);
}
}
main.html
<template>
<div>
<h2>Time Left:</h2>
<div>${timeLeft}</div>
</div>
</template>

TypeScript variable that is a typed function

I want to have a variable in a TypeScript class that is of the type "boolean isVisible()".
How do I declare it?
How do I assign this function for another instantiated object to this variable?
How do I call this function?
ps - This seems so basic but 10 minutes of searching and I couldn't find it.
function boolfn() { return true; }
function strfn() { return 'hello world'; }
var x: () => boolean;
x = strfn; // Not OK
x = boolfn; // OK
var y = x(); // y: boolean
Here's one way of doing it, though I'll be happy to work with you to figure out exactly what you're trying to achieve.
export module Sayings {
export class Greeter {
isVisible(): boolean {
return true;
}
}
}
var greeter = new Sayings.Greeter();
var visible = greeter.isVisible();
You could also use a property instead of a function. Your original question talks about a "variable" and a "function" as if they're the same thing, but that's not necessarily the case.
export module Sayings {
export class Greeter {
isVisible: boolean = false;
}
}
var greeter = new Sayings.Greeter();
var visible = greeter.isVisible;
greeter.isVisible = true;
Or something like this maybe?
export module Sayings {
export class Greeter {
constructor(public isVisible: () => boolean) {
}
}
}
var someFunc = () => {
return false;
}
var greeter = new Sayings.Greeter(someFunc);
var visible = greeter.isVisible();