Calling custom jQuery function inside Angular Component class - javascript

I have one custom query function written in a javascript file under the source folder (i.e. /src/assets/inlineedit.js) of Angular application.
Here's the content of the file.
$.fn.inlineEdit = function(replaceWith, connectWith) {
$(this).hover(function() {
$(this).addClass('hover');
}, function() {
$(this).removeClass('hover');
});
$(this).click(function() {
var elem = $(this);
elem.hide();
elem.after(replaceWith);
replaceWith.focus();
replaceWith.blur(function() {
if ($(this).val() != "") {
connectWith.val($(this).val()).change();
elem.text($(this).val());
}
$(this).remove();
elem.show();
});
});
};
Now, I want to call this function within Angular mycomponent.ts file and content looks as below:
import { Component, ViewChild, ElementRef } from '#angular/core';
#Component({
selector: 'app-pivotgrid',
templateUrl: './mycomponent.component.html',
styleUrls: ['./mycomponent.component.css']
})
export class mycomponent {
OnCellclick (event): void
{
var replaceWith = $('<input name="temp" type="text" />'),
connectWith = $('input[name="hiddenField"]');
$('#innerDiv').inlineEdit(replaceWith, connectWith);
}
}
But, I'm getting error like
Property 'inlineEdit' does not exist on type 'JQuery'
How to call jQuery functions inside Angular components?

You could use <any> type-casting like this:
(<any>$('#innerDiv')).inlineEdit(replaceWith, connectWith);
Or even better:
First install #types/jquery from npm
npm install #types/jquery --save-dev
Then add a local typings file and declare your plugin function in it
interface JQuery {
<your-plugin-name>(options?: any): any;
}
Then you can use your plugin.
Source: https://medium.com/all-is-web/angular-5-using-jquery-plugins-5edf4e642969

Related

typescript: Read class decorator files in node js

I've created a class decorator to read the permission for the angular component.
decorator.ts
function permissions(object: { [key: 'read' | 'write' | 'update' | 'delete']: string }[]) {
return (ctor: Function) => {
console.log(JSON.stringify(object));
}
}
components.ts
// employee.component.ts
#permissions([{ read: 'read-unique-id' }])
#Component({
selector: 'app-employee',
templateUrl: './app-employee.component.html',
styleUrls: ['./app-employee.component.css']
})
class Employee {
constructor() { }
}
// employee-details.component.ts
#permissions([{ read: 'read-unique-id' }, { write: 'write-unique-id' }])
#Component({
selector: 'app-employee-details',
templateUrl: './app-employee-details.component.html',
styleUrls: ['./app-employee-details.component.css']
})
class EmployeeDetails {
constructor() { }
}
I should be creating a file by reading the class name along with the permission details from decorator during compilation. Just a command to generate the below file.
Example: Permissions.ts
class Permissions {
static EMPLOYEE_READ = 'read-unique-id';
static EMPLOYEE_DETAILS_READ = 'read-unique-id';
static EMPLOYEE_DETAILS_WRITE = 'write-unique-id';
}
I believe I should create a Node JS app to read all the files and check for #permissions decorator and generate the above file. Is that correct?
If so, Can someone help me to achieve that. Read all the component.ts file and get the permissions details or is there any other method to achieve the same.
Update: I should read permission details from component.ts through decorator and generate Permissions.ts with help of Node JS app.
A more simple and type-safe way is to move in opposite direction and use a set of constants instead of strings, e.g. with enum:
enum Permissions {
EMPLOYEE_READ = 'read-unique-id';
...
}
...
#permissions([{ read: Permissions.EMPLOYEE_READ }, ...}])
A module that contains constants can be reused in backend application as well.

DOM manipulation is slow in angular while using jquery

I was developing an Angular app, in my dashboard.comp.ts I need to implement jquery event (due to other reason I have used jquery), jquery event working properly with my typescript objects. Now problem is when I click through jquery, DOM manipulation getting delay, so that, output getting delay like: 5/7 seconds.
dashboard.comp.ts
import { Component, OnInit} from '#angular/core';
import SensorServices from '../Services/Settings/SensorServices';
declare var $: any;
#Component({
selector: 'app-root',
templateUrl: '../Views/Dashboard.html',
providers: [SensorServices]
})
export class DashboardComponent implements OnInit {
public sensor: any;
constructor(private _sensorServices: SensorServices )
{
}
ngOnInit(): void {
this._sensorServices.getAll({})
.subscribe((result) => {
var self=this;
$(document).on('click', '.sensorSizeInDesign', function (e) {
self.sensor=result;
});
});
}
}
html
N.B: the given html is fewer basically element generated from server side, so there are multiple sensors. here is an example.
<div class='sensorSizeInDesign' data-sensorId="123"></div>
<h3>{{sensor.Port}}</h3>
For each click event Port getting delay to be changed.
avoid using jQuery inside angular applications. Therefor #ViewChild exists:
https://angular.io/api/core/ViewChild
Your click handler should be implemented this way:
function onClick() {
this._sensorServices.getAll({}).subscribe((result) => {
this.sensor=result;
})
}
HTML:
<div class='sensorSizeInDesign' (click)="onClick()" data-sensorId="123"></div>
<h3>{{sensor.Port}}</h3>
ngOnInit(): void {
this._sensorServices.getAll({})
.subscribe((result) => {
var self=this;
$( window ).on( "load", function(){
$(document).on('click', '.sensorSizeInDesign', function (e) {
self.sensor=result;
});
});
});
Try that
Finally i got the solution: just updating my jquery code:
ngOnInit(): void {
this._sensorServices.getAll({})
.subscribe((result) => {
var self=this;
$('.sensorSizeInDesign').click(function(e){
self.sensor=result;
})
});
}

On calling JavaScript file from Angular 2 project

I had written a calendar control in jQuery that I wanted to use in an Angular 2 project.
I've learned from other answers on this topic that I can use jQuery's getScript() API to call into external JavaScript files.
My calendar.component.ts looks like this:
import { Component, OnInit, AfterViewInit } from '#angular/core';
import { Auth } from '../auth.service';
declare var $:any;
declare var CustomCal:any;
#Component({
selector: 'app-calendar',
templateUrl: './calendar.component.html',
styleUrls: ['./calendar.component.css']
})
export class CalendarComponent implements OnInit {
private year : number;
myCal : any;
constructor(private auth : Auth) {
}
ngOnInit() {
}
ngAfterViewInit() {
this.year = 2017;
$.getScript('./app/calendar/zapCalendar.js', function(){
console.log("got call'd back");
this.myCal = new CustomCal(2017);
});
}
}
I get the console message "got call'd back", then an error message stating that CustomCal is not defined.
My CustomCal class is defined in zapCalendar.js as follows:
class CustomCal
{
constructor(nYear) {
this._mouseDown = false;
this._mouseDrag = false;
this._lastItem = 0;
this._nYear = nYear;
this.CreateCalendarFrame();
this.AddEventHandlers(this);
}
...
}
I've tried export'ing the class in the zapCalendar.js file, and also tried adding the following to the zapCalendar.js file:
$( function() {
var myCal = new CustomCal(2017);
});
What am I missing here?
Update:
I've just replaced this (in zapCalendar.js)
$( function() {
var myCal = new CustomCal(2017);
});
with this:
var x = new CustomCal(2017);
And now the calendar is rendering correctly. But I'd like (if possible) to get a reference to the calendar in my typescript. Is this possible?
$.getScript('./app/calendar/zapCalendar.js', function(){
console.log("got call'd back");
this.myCal = new CustomCal(2017);
});
The inner function here will not have the same this reference because it won't be called bound to your object. Since you're using TypeScript, you can just use an arrow function to change this behavior.
$.getScript('./app/calendar/zapCalendar.js', () => {
console.log("got call'd back");
this.myCal = new CustomCal(2017);
});
you need to export class then import it in your component
import {CustomCal} from "./app/calendar/zapCalendar";

How to include non node module Jquery plugin in an Angular 2 - Webpack App

I am using ng2-admin template and trying to include Sly in it, but I am struggling to add it.
I simply added jquery and Sly links inside my Index.html, but I am not sure how to Import Sly inside my Component.
webpack.common.js:
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
...
}),
analysis.component.ts:
import { Component, OnInit } from '#angular/core';
var Sly = require('../../../assets/plugins/sly/sly')
import 'style-loader!./analysis.scss';
#Component({
selector: 'analysis',
templateUrl: './analysis.html'
})
export class AnalysisComponent implements OnInit {
public acreage: any = {
condition: { good: 46, ok: 27, bad: 27 }
}
constructor() { }
ngOnInit() {
console.log('Sly', Sly)
var sly = new Sly('#frame', { horizontal: true }, {
load: function () {
console.log('load')
},
move: [
function () {
console.log('move 1')
},
function () {
console.log('move 2')
}
]
});
sly.init();
}
}
I am getting following error in browser's console:
Sly is not a constructor
An error simply means that the Sly plugin is not imported.
How to import and use non node module Jquery plugin inside Angular 2 Webpack app. The complete code of the template I am using can be found here.

Register Knockout.js component viewmodel from module in typescript

My viewmodel module has several classes, so I want to register a spesific class as component's viewmodel.
And it says: Component 'filter-table': Unknown viewModel value: [object Object]
This is what I have in my viewmodel module
module FilterVM {
export class FilterViewModel {
//some code
}
class FilterTableViewModel {
}
class AttributeTableViewModel {
}
class LayerAttributeViewModel {
}
}
export = FilterVM;
And this where I am trying to register
import FilterVM = require('Scripts/App/Components/AttributeTable/ViewModels/FilterViewModel');
ko.components.register('filter-table', {
viewModel: { require: FilterVM.FilterViewModel },
template: { require: 'text!Scripts/App/Components/AttributeTable/Views/FilterTableView.html' }
});
What is wrong with that?
SOLVED
The problem was here viewModel: { require: FilterVM.FilterViewModel }
Should be viewModel: FilterVM.FilterViewModel
require('Scripts/App/Components/AttributeTable/ViewModels/FilterViewModel');
You probably need to change this into a relative path. Even though TypeScript finds it at compile time ... the runtime library may not. Use something like require('../AttributeTable/ViewModels/FilterViewModel'); etc.

Categories

Resources