use directive return value - html

I have this dirctive that return title or null , how can i use this return value in html component ???
element:ElementRef;
#Input() pageTabTitle:string;
constructor(el:ElementRef) { this.element =el; }
ngOnChanges(): void {
setTimeout(() => {
this.hasTooltip(this.pageTabTitle);
})
}
hasTooltip(title:string) {
if(this.isOverflown()) {
return title;
} else {
return null;
}
}
isOverflown():boolean {
return this.element.nativeElement.scrollWidth >
this.element.nativeElement.clientWidth;
}
I want to use this value in tooltip title
[attr.data-original-title]="" // here I want to set return directive value

I think your directive doesn't have #Output - it couldn't return something:)
If you want that it emit some event with value, you should #Output property and emit it when you need.
Angular Io

Related

Ngx-formly check for focus in expressionProperties

I am using ngx-formly v: 5.5.10. I try to check if field is focused in the expressionProperties.
This is necessary for changing the value based on focus. Something like this:
expressionProperties: {
'model.testField': (m) => {
if (m.testField.value && testField.focus=true) {
return x;
} else {
return y;
}
}
}
Is there a formly built-in solution for checking focus in the expressionProperties?
Thanks for any help!
The field instance is passed as a third argument of the expression callback:
expressionProperties: {
'model.testField': (m, formState, field) => {
if (m.testField.value && field.focus === true) {
return x;
} else {
return y;
}
}
}

Angular automatically resolve strings as dates

I have a bunch of entities I've declared:
export class Meeting implements IHasId {
id = 0;
locationId = 0;
meetTime = new Date();
isFinalized = false;
imageId: number = null;
description = '';
name = '';
}
I have a generic crud service which handles resolving these to its original type
export class ApiResourceBaseService<T extends IHasId> {
get(id: number): Observable<T> {
return this.http.get<T>(`${this.apiUrl}/${this.route}/${id}`);
}
}
Typescript Generics are only superficial, so when I call get<T> typescript assumes my json is correct. However, My date objects are not resolved properly, they are resolved as string.
I have several entities, It would be annoying to create custom constructors/adapters to parse the dates.
does anyone have a better idea for automatically resolve dates?
I've created an interceptor to transform the data, In the future I'll probably just have auto generate my models and api resources from the api documentation and avoid this but for now I'm just using this hack:
export class ModelBinderInterceptor implements HttpInterceptor {
// regex of ISO 8601 Date.
DATE_TIME_TIMEZONE_REGEXP =
/^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/;
constructor() {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(tap((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
event = event.clone({body: this.modifyBody(event.body)});
}
return event;
}));
}
private modifyBody(body: any) {
return this.deserializeDates(body);
}
private deserializeDates(obj) {
if ((!(obj instanceof Object)) || (isString(obj))) {
return obj;
}
for (const key of Object.keys(obj)) {
const value = obj[key];
let date;
if (isString(value) && (this.DATE_TIME_TIMEZONE_REGEXP.test(value))) {
date = new Date(value);
// the parsing above may fail, in which case we use isNaN to check if the date is valid
if (isNaN(date.getTime())) {
return;
}
obj[key] = date;
}
this.deserializeDates(value);
}
return obj;
}
}

Angular, cannot access members of object in the array in custom pipes

Below is my custom pipe where I am unable to access the members of the customfilter array which is of type Item.
import { Pipe, PipeTransform } from '#angular/core';
import {Bus} from '/home/pavan/Desktop/Pavan/apstrtcAngular/src/app/Bus';
import { Item } from './Item';
#Pipe({
name: 'busFilter'
})
export class BusFilterPipe implements PipeTransform {
transform(items: Bus[], customfilter: Item): Bus[] {
if(!items || !customfilter)
{
return items;
}
return items.filter((item: Bus)=>
this.applyFilter(item, customfilter));
}
applyFilter(bus:Bus, customfilter: Item):
boolean{
if( customfilter[0].item_id){
if(typeof customfilter[0].item_id==='string'){
if(typeof bus.bustype==='string')
{
if(customfilter[0].item_id===bus.bustype)
{
return false;
}
} }
}
return true;
}
}
Below is my Item.ts and ng multiselect.
export class Item {
/**
* #type {number} id Unique numeric identifier.
*/
item_id: string;
item_text:string;
}
<ng-multiselect-dropdown class="ngfilter"
[placeholder]="'Select BusType'"
[data]="BusTypes"
[(ngModel)]="customfilter"
[settings]="dropdownSettings"
(onSelect)="onItemSelect($event)"
(onSelectAll)="onSelectAll($event)"></ng-multiselect-dropdown>
I am unable to find the issue here, I cannot look at the value of item_id during debugging too. please help me to know where the issue is. Thank you.
import { Pipe, PipeTransform } from '#angular/core';
import {Bus} from '/home/pavan/Desktop/Pavan/apstrtcAngular/src/app/Bus';
import { Item } from './Item';
import { forEach } from '#angular/router/src/utils/collection';
#Pipe({
name: 'busFilter'
})
export class BusFilterPipe implements PipeTransform
{
transform(items: Bus[], customfilter: Item[]): Bus[] {
let ResultSet: Bus[] = [];
if (!items || !customfilter) {
return items;
}
else if (customfilter.length == 0) {
return items;
}
else{
for (let i = 0; i < items.length; i++) {
for (let j = 0; j < customfilter.length; j++) {
if (customfilter[j].item_text === items[i].bustype) {
ResultSet.push(items[i]);
console.log("Result Set =" + ResultSet);
}
}
}
return ResultSet;
}
}
}
Based on your comments and my understanding of your code written in the pipe, modify your pipe like this (please read through the comments in the code):
transform(items: Bus[], customfilter: Item[]): Bus[] {
if(!items || !customfilter)
{
return items;
}
// making custom filter an Array if it isn't already
customFilter = customFilter instanceof Array ? customFilter : [customFilter];
// you seem to ignore the custom filters which don't have item_id
customFilter = customFilter.filter((eachCustom) => eachCustom.item_id);
// create an array of new items which satisfy your criteria
return items.reduce((acc, eachBus) => {
// if bus's bustype is not string then no need to filter
if (typeof eachBus.bustype != 'string') {
acc.push(eachBus)
}
else {
// if the bustype is a string
// then you have to see if this bus's bustype matches any of the custom filters and it's id type
// if not found then that bus should be present in the final bus list
let filterFound = customFilter.findIndex((eachFilter) => {
return (typeof eachFilter.item_id === 'string') && (typeof eachBus.bustype === 'string') && (eachFilter.item_id === eachBus.bustype);
});
if (filterFound === -1) {
// this bus is not found in the filter
acc.push(eachBus)
}
}
return acc;
}, [])
}
Below is a script in javascript to verify the result
function transform(items, customfilter) {
if(!items || !customfilter)
{
return items;
}
// making custom filter an Array if it isn't already
customFilter = customFilter instanceof Array ? customFilter : [customFilter];
// you seem to ignore the custom filters which don't have item_id
customFilter = customFilter.filter((eachCustom) => eachCustom.item_id);
// create an array of new items which satisfy your criteria
return items.reduce((acc, eachBus) => {
// if bus's bustype is not string then no need to filter
if (typeof eachBus.bustype != 'string') {
acc.push(eachBus)
}
else {
// if the bustype is a string
// then you have to see if this bus's bustype matches any of the custom filters and it's id type
// if not found then that bus should be present in the final bus list
let filterFound = customFilter.findIndex((eachFilter) => {
return (typeof eachFilter.item_id === 'string') && (typeof eachBus.bustype === 'string') && (eachFilter.item_id === eachBus.bustype);
});
if (filterFound === -1) {
// this bus is not found in the filter
acc.push(eachBus)
}
}
return acc;
}, [])
}
let buses = [{bustype: 1}, {bustype: "volvo-ac"}, {bustype: "volvo-non-ac"}, {bustype: "non-volvo-ac"}, {bustype: "non-volvo-non-ac"}]
let customFilter = [{item_id: "volvo-ac"}, {item_id: "non-volvo-ac"}]
console.log(transform(buses, customFilter))
// expected output won't contain the buses present in the filter

Angular: Cannot retrieve function parameter value as an object property selector

I have an issue trying to retrieve a function parameter value as an object property selector into a .filter() method.
This is my code:
myFunction(property, value) {
function myFilter(obj) {
return obj.details.name == value;
}
return this._http.get(this.Url).map((response: Response) => response.json().filter(myFilter));
}
I want to replace return obj.details.name == value; by return obj.property == value;.
obj.property is the parameter of my function myFunction(property, value). The value parameter value works fine and is well retrieved.
This is what I want:
getFilteredFMsBy(property, value) {
function specificFilter(obj) {
return obj.property == value;
}
return this._http.get(this.Url).map((response: Response) => response.json().filter(specificFilter));
}
If I define the value of property in the function, same case. It doesn't work:
getFilteredFMsBy(property, value) {
property = "details.name";
function specificFilter(obj) {
return obj.property == value;
}
return this._http.get(this.Url).map((response: Response) => response.json().filter(specificFilter));
}
Any idea?
Seems like you need to access object[prop][prop2] given the object and the string "prop.prop2"
from this answer: Javascript: Get deep value from object by passing path to it as string you can do deepFind:
function deepFind(obj, path) {
var paths = path.split('.')
, current = obj
, i;
for (i = 0; i < paths.length; ++i) {
if (current[paths[i]] == undefined) {
return undefined;
} else {
current = current[paths[i]];
}
}
return current;
}
then do
getFilteredFMsBy(property, value) {
property = "details.name";
function specificFilter(obj) {
return deepFind(obj, property) == value; // <-- use it here
}
return this._http.get(this.Url).map((response: Response) => response.json().filter(specificFilter));
}
How about this?
getFilteredFMsBy(property: string, value:any) {
return this._http.get(this.Url).map((response: Response) => response.json().filter((obj) => { return obj[property] == value; }));
}

How to add image attributes in Quill editor? I want to add 'alt' and 'title' attribute

When I upload an image, only its 'src' is saved. I want to add alternate text and title for SEO purpose. I tried searching for a module in the Quill documentation, but could not find any.
Maybe not the direct answer but related.
Here is the solutions to keep attributes for image when initializing from full text html.
Solution1:
class ImageBlot extends Image {
static create(value) {
if (typeof value == 'string') {
return super.create(value);
} else {
return value;
}
}
static value(domNode) {
return domNode;
}
}
Quill.register(ImageBlot);
Solution2:
class ImageBlot extends Image {
static get ATTRIBUTES() {
return [ 'alt', 'height', 'width', 'class', 'data-original', 'data-width', 'data-height', 'style-data' ]
}
static formats(domNode) {
return this.ATTRIBUTES.reduce(function(formats, attribute) {
if (domNode.hasAttribute(attribute)) {
formats[attribute] = domNode.getAttribute(attribute);
}
return formats;
}, {});
}
format(name, value) {
if (this.constructor.ATTRIBUTES.indexOf(name) > -1) {
if (value) {
this.domNode.setAttribute(name, value);
} else {
this.domNode.removeAttribute(name);
}
} else {
super.format(name, value);
}
}
}
Quill.register(ImageBlot);
You can specify the whitelist for attributes with solution2.