背景(領域外)をクリックしたら閉じる、とか
ドロップダウンなどを表示したときに、領域外をクリックしたら閉じたい。 HTMLだと、どのように実装するのが一般的なのかわからなかったのでAngularのUI Bootstrapを参考にしてみたよ。
Dropdown
documentにイベントハンドラを登録。
// https://github.com/angular-ui/bootstrap/blob/v1.1.0/src/dropdown/dropdown.js#L13 $document.on('click', closeDropdown); // ... var closeDropdown = function(evt) { // ... // dropdown内をクリックかつ'outsideClick'が設定されている場合は閉じない var dropdownElement = openScope.getDropdownElement(); if (evt && openScope.getAutoClose() === 'outsideClick' && dropdownElement && dropdownElement[0].contains(evt.target)) { return; } // ... openScope.isOpen = false; // ... };
補足: dropdownは複数開くことができないようになっている。uibDropdownServiceが管理している。
Modal
自身(全領域カバーしている)にイベントハンドラを登録。
// https://github.com/angular-ui/bootstrap/blob/v1.1.0/src/modal/modal.js#L165 element.on('click', scope.close);
documentに登録する方法だとこんな感じでしょうか。
class Controller { closeHandler: () => void; /*@ngInject*/ constructor( private $document: ng.IDocumentService, private $element: ng.IAugmentedJQuery, private $scope: ng.IScope ) { } $onInit() { this.closeHandler = () => { this.close(); this.$scope.$apply(); }; this.$element.on('click', ($event) => { // this.$document.on を無効にするため $event.stopPropagation(); }); } $onDestroy() { this.close(); } open() { // 何かの処理 // ... this.$document.on('click', this.closeHandler); } close() { // 何かの処理 // ... this.$document.off('click', this.closeHandler); } } const components: ng.IComponentOptions = { templateUrl: 'foo.html', controller: Controller, bindings: {} }; export default components;
Angularを1.5から1.6に移行
1.5.6から1.6.1に移行。参考にしたのは
- Angular 1.6 is here, this is what you need to know
- https://docs.angularjs.org/guide/migration#migrating-from-1-5-to-1-6
など。
対応箇所
$onInit
初期化のロジックが変更。(bindings
された変数がconstructor
内では利用できなくなった。)
全てのDirectiveとComponentに$onInit
を用意し、初期化時の処理を$onInit
内に記述。
(この変更は、書き方が統一されるので嬉しい。)
The reasoning behind this change is that it is not idiomatic JavaScript to bind properties to an Object before its constructor has been called ...
$http
$httpのsuccess()
とerror()
がなくなった。then()
とcatch()
に置き換え。
hash-prefix
hash-prefixが!
に変更。
$q
PromiseのRejectionが未処理の場合、警告が出るようになった。
Possibly unhandled rejection:
$uibModalの利用している場合、backdropクリックでモーダルを閉じると警告がでるので、一応以下のように対応。
this.$uibModal .open({ templateUrl: 'demo.html', }) .result.catch(angular.noop);
メモ
errorOnUnhandledRejections
を利用する。
(この方法だとエラーが捕捉できない)
javascript - Possibly unhandled rejection in Angular 1.6 - Stack Overflow
app.config($qProvider => { $qProvider.errorOnUnhandledRejections(false); })
CircleCIのChromeを最新版に
Chromeのバージョンが低いため、E2Eが失敗してしまう。
Linux Package Signing Keysをインストールしてsudo apt-get --only-upgrade install google-chrome-stable
で解決。
- Update Chrome in container image - Feature Requests - CircleCI Community Discussion
- Linux Software Repositories – Google
dependencies: pre - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - - sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' - sudo apt-get update - sudo apt-get --only-upgrade install google-chrome-stable
ユニットテスト(Karma)もTypeScriptで
別記事 -> ユニットテスト(Karma)もTypeScriptで: karma-webpack編 - ryotah’s blog
preprocessorsに追加すればいいだけだった。
GitHub - sergeyt/karma-typescript-preprocessor: TypeScript preprocessor for karma-runner
// karma.conf.js module.exports = function(config) { config.set({ preprocessors: { '**/*.ts': ['typescript'] }, typescriptPreprocessor: { options: { sourceMap: false, target: 'es5', module: 'commonjs', }, transformPath: function(path) { return path.replace(/\.ts$/, '.js'); } }, plugins: [ 'karma-typescript-preprocessor' ] }); };
Karmaのバージョンは0.13.22。ちょっと古い。