Blog Archives

May 29th, 2017
1:18 pm
CouchDB View emitting the same document twice

Posted under CouchDB
Tags , , ,

I had a bug whereby my view was emitting the same place document twice. This was strange as the database clearly did not contain 2 copies of the document. I had seen what appeared to be a similar issue before bud at the time did not track down the cause.

It turned out to be a bug in the view definition. The original (buggy) version follows:-

function (doc) {
  if (doc.type == ‘place’) {
      emit([doc.address.postTown, doc.address.locality, doc.name, doc._id, 0], null);
      emit([doc.address.postTown, doc.address.locality, doc.name, doc._id, 1], {_id: doc.placeFeaturesId});
  }
}

The problem with this is that when doc.placeFeaturesId is null/undefined, the second emit emits its key plus an “_id” with an undefined/null value in the generated json. The result of this is that when using ?include_docs=true to include the documents, CouchDB applies a default behaviour due to the null, and emits the place document again a second time. The following fix prevents the second emit when there are no placeFeatures present, which prevents the place document being emitted a second time. This solves the problem:-

function (doc) {
  if (doc.type == ‘place’) {
      emit([doc.address.postTown, doc.address.locality, doc.name, doc._id, 0], null);
      if (doc.placeFeaturesId) {
        emit([doc.address.postTown, doc.address.locality, doc.name, doc._id, 1], {_id: doc.placeFeaturesId});
      }
  }
}

The lesson here is to be careful to handle undefined or null values in the view code when emitting entries in a view definition as this can cause strange behaviour such as the duplicates above.

No Comments »

May 26th, 2017
12:55 pm
Dynamically updating css classes on child components from a parent property

Posted under Angular & CSS & PrimeNG
Tags , , ,

I was using a button component to encapsulate the primeNG one, to allow it to responsively change to an icon only button at smaller screen widths. Whilst in theory I could have dynamically modified the internal primeNG button CSS, this was complex and I did not want  to become tightly coupled to it. My button component therefore simply selected one of 2 buttons via a media query, setting the unwanted one to display:none.

I wanted any classes added to the top level ss-button to be set on the underlying primeNG buttons. One use of these buttons was in a home brewed tab component, and  I was dynamically changing the button colour via ui-button-primary, ui-button-secondary so that the active tab had a ‘primary’ coloured button and the inactive ones were ‘secondary’ which caused them to become uncoloured ghost buttons – ideal for my requirement.

During refactoring to replace the ‘full size only’ primeNG buttons with the resizing ss-buttons I introduced a bug and the colour change failed to work. The initial (incorrect) refactored code was as follows:-

ss-tab-toolbar.component.html

<ng-container *ngFor="let tab of tabs">
<app-ss-button [label]="tab.label" [icon]="tab.icon" (click)="setActiveTab(tab)"
[ngClass]="{'ui-button-primary': isActiveTab(tab), 'ui-button-secondary': ! isActiveTab(tab)}"></app-ss-button>
</ng-container>

ss-button.component.html

<button pButton type="button" [title]="label" [label]="label" [icon]="icon" class="ss-button icon-text"
[ngClass]="class" ></button>
<button pButton type="button" [title]="label" [icon]="icon" class="ss-button icon-only"
[ngClass]="class" ></button>

ss-button.component.ts

@Component({
selector: 'app-ss-button',
templateUrl: './ss-button.component.html',
styleUrls: ['./ss-button.component.scss']
})
export class SSTabButtonComponent {

@Input() label: string;
@Input() icon: string;
@Input() class: string;

constructor() { }
}

The issue was that I was using [ngClass] dynamically to update the classes on the <app-ss-button> in ss-tab-toolbar.component. html. This used to work for the PrimeNG buttons, but now would have no effect as the classes need to be changed on the child buttons not the encapsulating parent. A simple change of [ngClass] to [class] fixed the problem, as the parent style change then updated the property on the parent component which was then picked up by the children correctly.

modified ss-tab-toolbar.component.html

<ng-container *ngFor="let tab of tabs">
<app-ss-button [label]="tab.label" [icon]="tab.icon" (click)="setActiveTab(tab)"
[class]="{'ui-button-primary': isActiveTab(tab), 'ui-button-secondary': ! isActiveTab(tab)}"></app-ss-button>
</ng-container>

Happily the dynamic nature of angular meant that this worked perfectly for tab changes – the change on the parent class was propagated correctly to the child and the button colours changed correctly.

I was wondering initially whether I would need to involve observables to make this work but this was not the case – this kind of dynamic propagation pattern is worth remembering in future.

No Comments »

May 18th, 2017
5:56 pm
Vertically Centering items in a div–2017 version!

Posted under Angular & CSS & PrimeNG & Web
Tags ,

I posted about this kind of issue back in 2010 here.

Nowadays for my own project work I am happy to assume recent browsers, in particularly IE11 at least (noting that even this has been out a while now – it was released 4 years ago now so a reasonable start point).

This means that I am happy to use css Flex which makes this insanely simple compared to the old days. You just need display:flex;align-items:center in the container div and its content items will centre vertically.

I’ve just used this on a PrimeNG data list component to centre left thumbnails correctly in a list item with no issues.

Quite why we have had to suffer for so many years with arcane tricks (or risk ridicule by making it simple using tables for layout) is beyond me, but there we are.

No Comments »

May 18th, 2017
11:22 am
Webstorm IDE–Oragnising Imports Tips/Gotchas

Posted under TypeScript & WebStorm
Tags ,

1/ Organising imports does not seem to happen automatically when it should. To organise imports for a given folder or the project, select the appropriate level in the navigator then hit Code/Optimise Imports or ctrl+alt+0 as detailed here.

2/ TSLint gives errors about double quotes in imports as it prefers single quotes in all the code (double quotes for html), but Webstorm uses double quotes by default when organising imports. You can change Webstorm to use single quotes as per this post here.

No Comments »

May 14th, 2017
10:53 am
Web App container layout– how to fill space to right

Posted under Angular & CSS & PrimeNG
Tags , ,

I was trying to allow a left div for a menu to have a percentage width, possibly with a fixed min-width.

I then wanted to add a right div which filled all the remaining space to the right, to form a content pane.

My initial attempts which failed were:-

1/ Float both divs left – this partly works e.g. if I gave 25% width to the left and 75% width to the right, i.e. I had to assign width. If I then gave a min-width to the left, the right div drops underneath when the min-width kicks in.

2/ Per this post here, I took the float out of the right div. Whilst it extended to fill the right hand space, it also filled the left hand space, and placing e.g. a PrimeNG toolbar in the right hand pane resulted in a mess where the height of the toolbar filled the whole height of both divs. This was all due to the interaction of the floated and non floated div – the non floated one just flowed around the left hand floated div, and its content was in fact also hiding underneath the right one. In fact the comments mention that the proposed solution in the post does not work exactly as I found.

Finally an interesting solution which did work is this post here. The right float is not floated but is set to overflow:hidden. This triggers a Block Formatting Context, which interacts with the float to fill the remaining space. The right div becomes a BFC which prevents sibling floats from intruding on them, and also prevents descendant floats from escaping. The post explains the details on this well.

This worked correctly, even when the min-width was used in conjunction with a percentage width for the left div. A plunker showing a simple example of the BFC may be found here.

In the end I abandoned this approach of rolling my own layout. I was using PrimeNG components, and PrimeNG comes with a Grid CSS layout component which does full responsive 12 column based layout. It is nestable, and adaptable automatically for different screen widths via media queries. It is also used internally for the PrimeNG components, so will play nicely with them and will be less prone to side effects. I note from the comments that Bootstrap responsive column layout does not work well with PrimeNG, so I stuck with PrimeNG as it is flexible and easy to use.

Another alternative for grid layout which is big in this area is Foundation, which is also reviewed and compared with Bootstrap here. Bootstrap may be found here. Both Foundation and Bootstrap are frameworks offering components and css/theming as well as grid layout so would likely fight with Primefaces as this post indicates. It looks like you may be able to just get the grid with Foundation by now, not sure with Bootstrap.

No Comments »

May 11th, 2017
10:25 am
Angular-cli error on ng build: “The "@angular/compiler-cli" package was not properly installed.”

Posted under Angular & PrimeNG
Tags ,

I got this error when trying to build and run the primeng-quickstart-cli per the readme in the git project

E:\Dev\angular\primeng-quickstart-cli>ng build
You seem to not be depending on "@angular/core". This is an error.

E:\Dev\angular\primeng-quickstart-cli>ng serve
The "@angular/compiler-cli" package was not properly installed.
Error: The "@angular/compiler-cli" package was not properly installed.
    at Object.<anonymous> (E:\Dev\angular\primeng-quickstart-cli\node_modules\@ngtools\webpack\src\index.js:14:11)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (E:\Dev\angular\primeng-quickstart-cli\node_modules\@angular\cli\tasks\eject.js:10:19)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)

E:\Dev\angular\primeng-quickstart-cli>

I tried upgrading angular-cli as per here, but this did not solve the problem.

Interestingly when I tried to start the alternative primeng-quickstart-webpack project using ng-serve, I got the same error as above.

However, when following the correct (and different) instructions for primeng-quickstart-webpack  as follows it worked:-

npm install

npm run start:webpack

I therefore tried to use these npm install/run commands on the primeng-quickstart-cli project but it was clearly not set up for this build/run mechanism:-

E:\Dev\angular\primeng-quickstart-cli>npm run start:webpack
npm ERR! Windows_NT 6.1.7601
npm ERR! argv "E:\\Program Files\\nodejs\\node.exe" "E:\\Program Files\\nodejs\\node_modules\\n
npm ERR! node v7.10.0
npm ERR! npm  v4.2.0

npm ERR! missing script: start:webpack
npm ERR!
npm ERR! If you need help, you may report this error at:
npm ERR!     <https://github.com/npm/npm/issues>

npm ERR! Please include the following file with any support request:
npm ERR!     C:\Users\SteveW\AppData\Roaming\npm-cache\_logs\2017-05-11T10_08_50_957Z-debug.log

At present the issue with primeng-quickstart-cli is not a blocking one – the other starter  primeng-quickstart-webpack looks preferable as it is a simple full CRUD table app whereas the other starter it a trivial one whch just outputs a message in response to a button click.

These StackOverflow posts here and here discuss the error, but I did not appear to be missing the basic config. This post might be more relevant, and advises downgrading first then re-upgrading, but it refers to angular 2 rather than 4.

I hope to learn and resolve these build issues and errors at some point soon though and gain a better understanding of what is going on/ what are the alternatives.

No Comments »

May 8th, 2017
12:41 pm
CouchDB continually fills the log with Shard/disk loading/database errors.

Posted under CouchDB
Tags ,

In my case the log had grown to nearly 1GB, and there does not appear to be any log rotation set up by default!

It turns out that this will occur if you have not configured the node after installation – either for single node operation, or as a cluster.

This can easily be done via the configuration option in Fauxton, and at the same time it allows you to set credentials for the admin account.

Doing this prevented the log spamming and log growth was then minimal.

This post here discusses the issue.

No Comments »

May 8th, 2017
12:15 pm
Ionic error on startup – ionic Error: ENOENT: no such file or directory

Posted under Ionic
Tags , ,

The cause of this is not immediately obvious, but it blocked startup via ionic serve – the error continues to cite a template error of some kind.

The actual issue is an invalid file path on the templateUrl attribute of the @Component({ decorator of the relevant component mentioned in the error. I found a variety of different file paths used – some with no path and just the filename, some with “./” on the front, and the offending one had a prefix of “src/” which caused the failure.

Just correcting the file path on the attribute fixes the problem.

No Comments »

May 7th, 2017
8:05 pm
Angular 2 expressions containing observables cause null glitch on page display

Posted under Angular
Tags ,

The following expressions caused a brief glitch whereby null was displayed prior to the observable locationsCount emitting its value:-

<span text-capitalize>show all{{showAllActive ? ' ' + (locationsCount | async) : ''}}</span>

This makes sense as the observable with its async pipe, | async , which handles the observable, is part of a string expression. In other cases where the observable is e.g. a returned list, then you would just get an empty list with no entries. However in this case, Angular needed to evaluate and display the expression and so null was briefly displayed instead of the value of locationsCount.

The easiest way around this is to use a logical or which acts as a null coalescing operator in JavaScript/TypeScript, to replace the null with a suitable constant string:-

<span text-capitalize>show all{{showAllActive ? ' ' + (locationsCount | async)||' ' : ''}}</span>

The use of (locationsCount | async) || ‘ ‘  checks the first operand regardless of type, and if it is falsey, the second operand is taken. This is explained in this post here.

An alternative, a more complex solution which also worked in my case and may be interesting in other cases, is to concatenate the observable with another observable which emits a constant string using Observable.of(). The concat method emits all the values from each of the passed observables in turn, proceeding to the next one when an observable closes, as detailed in the RxJS api docs here. Therefore, the constant observable emits a value and completes/closes immediately which prevents the null glitch, followed by the locationsCount observable when it finally emits a value (which came from a mapped http api call):-

initial version without constant observable:-

this.locationsCount = this.locationsAutoCompleteService.getLocationsCount()
.map(count => {
let countString: string = this.formatLocationsCount(count);
return countString;
});

Alternative version with concatenated constant observable:-

this.locationsCount = Observable.of(' ').concat(
this.locationsAutoCompleteService.getLocationsCount()
.map(count => {
let countString: string = this.formatLocationsCount(count);
return countString;
})
);

No Comments »

May 1st, 2017
4:03 pm
Typescript duck typing error when casting a reference.

Posted under Angular & TypeScript
Tags , , ,

The following code fragment in a dao gave an error when casting the response json. The cause is not clear, but 2 code variations were tried:-

//API calls
getFeatures(): Observable<FeaturesSearchResult> {
return this.http.get(this.queryFeatures())
      // *** This version originally failed citing that property total_rows did not exist
.map(response => {return <FeaturesSearchResult>(response.json())});
}

I then tried using the “as” operator for the cast instead of the <> syntax. This worked. Strangely, right at the end I managed to get an example with the”<>” syntax working too, but the reason and differences were not at all clear.
However, I noted that the latter is also the preferred syntax now, as unlike the “<>” syntax it is also compatible with JSX/.tsx syntax (JSX is an embeddable React xml-like syntax which transforms into JavaScript)
See here for details on JSX/.tsx, and on the React wikipedia entry. The working code fragment follows:-

//API calls
getFeatures(): Observable<FeaturesSearchResult> {
return this.http.get(this.queryFeatures())// *** This version originally failed citing that property total_rows did not exist
      // *** This version worked by using the “as …” syntax for casting rather than <>
.map(response => {return response.json() as FeaturesSearchResult});
}

The full listing of the code for the working version (less imports for brevity) follows:-

features-dao.ts
@Injectable()
export class FeaturesDao {
constructor(private appConfig: AppConfig,
private http: Http) {}

//API calls
getFeatures(): Observable<FeaturesSearchResult> {
return this.http.get(this.queryFeatures())
.map(response => {return response.json() as FeaturesSearchResult});
}

//API query definitions
queryFeatures(): string {
return `${this.appConfig.apiBase}_design/places/_view/featuresByOrdinal?include_docs=true`;
}

}
export interface FeaturesSearchResult extends CouchDBResult<FeaturesSearchResultRow> {}
export interface FeaturesSearchResultRow extends CouchDBResultRow<number[], any, FeatureDoc> {}
couchdb-result.ts
export interface CouchDBResult<R extends CouchDBResultRow<any,any,any>> {
total_rows: number;
offset: number;
rows: R[];
}

export interface CouchDBResultRow<K,V,D> {
id: string;
key: K;
value: V;
doc?: D;
}
feature-doc.ts
export interface FeatureDoc extends CouchDBDoc {
ordinal: number;
name: string;
description: string;
searchable: boolean;
rateable: boolean;
}

No Comments »