Dailycode.info

Short solution for short problems

Angular: date pipe not showing in IE when using time filter.

I'm having a lot of IE11 problems today with Angular 4. I understand that the framework focusses more one real browsers, unfortunately in the corporate world IE11 is still not dead. During development I use Chrome, at test phase the users use IE 11 and then the problems come.

Today I already had some difficulties on this subject. No the date pipe of Angular is not working as expected in IE11. When I set the date format to: dd/MM/yyyy HH:mm for example, it works in Chrome. But in IE it is showing nothing. It has something to do with a bug in the browser, when using the minutes (mm) it stops working. If you only use the date format (dd/MM/yyyy) in the pipe, it works for IE11.

So, after some lookup I decided to make my own pipe. Because for example the momentJS was to heavy to use only for this problem.

This is how the pipe code looks:

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'dateNLBE'
})
export class DateNlBePipe implements PipeTransform {
transform(value: Date, type: string = ''): string {
if (value !== null) {
return `${value.toLocaleDateString('nl-BE')} ${value.getHours() < 10 ? '0' + value.getHours() : '' + value.getHours()}:
${value.getMinutes() < 10 ? '0' + value.getMinutes() : '' + value.getMinutes()}`;
}
return '';
}
}


Now you can use it in your code like this:

<td>{{o.CreatedOn | dateNLBE }}</td>

And this works both in IE and Chrome.


Angular: Formbuilder and select showing default value in Chrome, not in IE

I had a problem with FormBuilder and IE. In Chrome everything worked fine, the select first was empty and required. If no value selected then it would give an error. But in IE the first value was shown in the select but not selected. Very confusing. 

To solve this I had to add a default option to the select with value null:

<select id="type" class="form-control" formControlName="Type" [class.is-invalid]="hasError('Type')">
<option [ngValue]="null">Please select value</option>
<option *ngFor="let o of ficheTypes" [ngValue]="o.name">{{o.name}}</option>
</select>

Now in the initialize form I added null as default value for the model that was binbed to the select. (Marked below)

 private initializeForm(): void {
this.formGroup = this.formBuilder.group({
'Id': FormBuilderHelper.getFormEntry('Id', true, false, this.fiche, 0),
'Type': FormBuilderHelper.getFormEntry('Type', true, false, this.fiche, null),
});

tslint: for .. in .. gives error: (... in ...) statements must be filtered with an if statement (forin)

I was rewriting a pipe from angular 1 to 4. There was a statement where tslint was giving me this error:


The code looked like this:
for (i in o) {
r.push(o[i]);
}

To get rid of the warning from tslint, you have to write an if inside the for loop to check if the proprty really exitst:

for (i in o) {
if (o.hasOwnProperty(i)) {
r.push(o[i]);
}
}


Because the object o is not an array, it expects the if statement to be present after the for loop. A switch statement cannot be used either without tslint warnings.


Angular: download blob in IE11 not working.

I had an Angular 4 web app where the user could open a document coming as a blob from our DB. In IE11 this didn't work the normal way. The code looked like this:

try {
	let link = window.document.createElement('a');
	let blob = new Blob([data], { type: document.FileType });
	let url = window.URL.createObjectURL(blob);
	
	link.setAttribute('href', url);
	link.setAttribute('download', document.FileName);

	let event = window.document.createEvent('MouseEvents');
	event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
	link.dispatchEvent(event);

	defer.resolve(true);
}
catch (ex) {
	self.logService.log(ex);
	defer.resolve(false);
}

The problem was that the link was not supposed to have the href and download attribute set for IE. Also the url had to be build up in a slightly different way using the msSaveOrOpenBlob:

try {
	let link = window.document.createElement('a');
	let blob = new Blob([data], { type: document.FileType });
	let url = null;

	if (navigator.msSaveBlob || navigator.msSaveOrOpenBlob) {
		url = navigator.msSaveOrOpenBlob(blob, document.FileName);
	} else {
		url = window.URL.createObjectURL(blob);
		link.href = url;
		link.setAttribute('download', document.FileName);
	}

	let event = window.document.createEvent('MouseEvents');
	event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
	link.dispatchEvent(event);

	defer.resolve(true);
}
catch (ex) {
	self.logService.log(ex);
	defer.resolve(false);
}

This check if (navigator.msSaveBlob || navigator.msSaveOrOpenBlob) will see if the browser needs to use a different way to open the BLOB. I believe this is specific for Microsoft browsers. More on this here. This worked for me, I hope it can help you.


AngularJS : Smart table select search not working in IE 11

I was building a web site and testing it in Chrome. Worked fine. Untill the users started testing in IE!! There the filtering in the table using dropdowns (select) didn't work. After some looking around I found out that the smarttable was binding to the input event. But IE only fires the change event with select. So the binding didn't work. The smarttable version 2.1.8 has an option to bind the search to another event:

<select st-input-event="change" st-search="Month" class="form-control">
    <option value="">All</option>
    <option ng-repeat="row in vm.filteredConsignments | unique:'Month'" value="{{row.Month}}">{{row.Month}}</option>
</select>

The st-input-event attribute allows you to change the binding. Now it can work with the change event, it still works in Chrome, but now also in IE (in my case IE11).




MSSQL: convert datetime to time

I needed to show the time between a start and end datetime in one record in the DB. This could be done using the CONVERT function:

CONVERT(char(10),  EndTime - StartTime, 114) as TotalTime

Then the result looked like this:



IIS copy files to file share in API or web site

Recently, I needed to copy some files from a database to a file share in a .Net web API that runs on an IIS. First I was trying to run the application pool using a domain user, but I couldn't get it working. The application pool keeps stopping, even if the username and password is correct and the local policies are correct.

So I found another better way to do it. In stead of giving the user permissions on the file share. I gave the server permissions on the file share. Then I ran the application pool under the NetworkService and it works.

On the file share under security, put DOMAIN\SERVERNAME and give modify rights (do not forget to include computers in de AD search). Thats it. Now the server can write to this specific location, no harm can be done. In fact, giving a user permissions can be more dangerous, because he can access it anywhere.


AngularJS and .Net WEB.API: 405 (Method Not Allowed) for PUT and DELETE

I was having some problems with put and deletes. When I ran the code on the localhost, no problem, but after installing on the servers, delete calls were giving CORS errors. I tried to figure out what was going on, but I lost some time. First I rewrote the methods to POST methods, this worked. But when a new occasion came to look for a better solution I found it here.

The thing is that DELETE and PUT are sending a OPTION request first to the API on the server. If this method is not there, then it will not work. The error message will not really point you into the right direction. 

But instead of adding the OPTION methods foreach DELETE or PUT you could also disable WebDAV in IIS. That really does the trick. No code changes needed, just a simple configuration.

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
    <remove name="WebDAVModule"/>
  </modules>
  <handlers>
    <remove name="WebDAV" />
  </handlers>
</system.webServer>

And thatis it.

No more of these now: