ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

【AngularJS1.5.x】directiveのtemplateにfilterを引数で渡したい

渡したかった。

  • index.html
<first-directive main="main.myDirective" filter-name="number"></first-directive>
  • app.js
    .directive('firstDirective', ['$log', 'FigureService', function ($log, FigureService) {
        return {
            restrict: 'E',
            scope: {
                directiveMain: '=main',
                filterName: '=filterName'
            },
            controller: 'Main',
            template: '<ul>' +
                      '    <li ng-bind="directiveMain.triangle + \':三角形\'"></li>' +
                      '    <li ng-bind="directiveMain.circle + \':円\'"></li>' +
                      '    <li ng-bind="directiveMain.trapezoid + \':台形\'"></li>' +
                      '    <li>{{directiveMain.circle | filterName}}</li>' +
                      '</ul>',
            link: function(scope, element, attrs, controller) {
            }
        }
    }])

エラーでした。

Error: $injector:unpr Unknown Provider

Unknown provider: filterNameFilterProvider <- filterNameFilter

うーむ。filterとして認識されていない?

            template: '<ul>' +
                      '    <li ng-bind="directiveMain.triangle + \':三角形\'"></li>' +
                      '    <li ng-bind="directiveMain.circle + \':円\'"></li>' +
                      '    <li ng-bind="directiveMain.trapezoid + \':台形\'"></li>' +
                      '    <li>{{directiveMain.circle | filter:filterName}}</li>' +
                      '</ul>',

filter:っていう文字を追加

Error: filter:notarray Not an array

Expected array but received: 314.1592653589793

「配列希望だけど、違うよ」って感じ。何故だ。

次は普通に使ってみる

                      '    <li>{{directiveMain.circle | number}}</li>' +

これは動いた。

うーむ。。。

30分経過

だんだん英語の記事の引っぱりかたがわかってきた。

「angularjs filter argument」とかで検索してしまうと、「angularjsのfilterで引数の渡し方」みたいな記事しか引っぱってこない。

「how can i ~」とか「how to ~」とかつけると、「やり方」=> 手順っぽい記事を探してくれる。

「how to pass filter to a directive」とかで検索するとマッチした。(+ in angularjs とか書くと完璧かも)

stackoverflow.com

で、directivescopeで渡したいfilterは、templateで実行することができないっぽい。

実現できた書き方としてこんな感じ。

    .directive('firstDirective', ['$log', 'FigureService', '$filter', function ($log, FigureService, $filter) {
        return {
            restrict: 'E',
            scope: {
                directiveMain: '=main',
                filterName: '=filterName'
            },
            controller: 'Main',
            template: '<ul>' +
                      '    <li ng-bind="directiveMain.triangle + \':三角形\'"></li>' +
                      '    <li ng-bind="directiveMain.circle + \':円\'"></li>' +
                      '    <li ng-bind="directiveMain.trapezoid + \':台形\'"></li>' +
                      '    <li><input type="text" ng-model="directiveMain.trapezoid" ng-blur="myBlur()" ng-model-options="{updateOn: \'blur\'}"></li>' +
                      '</ul>',
            link: function(scope, element, attrs, controller) {
                // directiveがインスタンス生成される度に実行される
                $log.info(scope);
                $log.info(element);
                $log.info(attrs);
                $log.info(controller);

                // Serviceを仕様して、directiveのscopeを変更
                // controllerとbindするとmodelがシェアされる
                scope.directiveMain.triangle = FigureService.triangle(10, 5);
                scope.directiveMain.circle = FigureService.circle(10);
                scope.directiveMain.trapezoid = $filter(scope.filterName)(FigureService.trapezoid(1320, 5, 3)); // ここの部分

                scope.myBlur = function() {
                    console.log($filter(scope.filterName)(scope.directiveMain.trapezoid));
                };
            }

linkで実行すれば良い。

だがしかし、これだと初回の実行だけで、値を変えた場合はfilterが実行されない。

なので、常に実行する場合はeventの発火を監視して、filterを実行すればいいんじゃないかなと思う。

CakePHP3をインストール

(前もやった気がするけど。。。)

全然覚えていなかったのでメモ

環境

$ sw_vers 
ProductName:  Mac OS X
ProductVersion: 10.11.5
BuildVersion: 15F34

el capitanです。

php5.6をインストール

phpbrewphpenvとかでインストールしようとしたらapxsでハマる(´;ω;`)ブワッ

なので、プリインストールされているphpをバージョンアップしました。

$ brew update
$ brew upgrade
$ brew tap homebrew/php
$ brew tap homebrew/dupes
$ brew install php56 --with-apxs2=/usr/sbin/apxs 

==> Installing php56 from homebrew/php
Error: Cannot install homebrew/php/php56 because conflicting formulae are installed.

あらら

php55をunlinkして再度実行

$ brew unlink php55

$ brew install php56 --with-apxs2=/usr/sbin/apxs 
==> Summary
🍺  /usr/local/Cellar/php56/5.6.23: 331 files, 48.9M

おk

$ php -v
PHP 5.6.23 (cli) (built: Jun 24 2016 21:14:33) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies

インストールしたいphpを使いたいので、Apache側の設定も変更する

$ sudo vim /etc/apache/httpd.conf

####
#LoadModule php5_module libexec/apache2/libphp5.so
LoadModule php5_module /usr/local/Cellar/php56/5.6.23/libexec/apache2/libphp5.so
####

intlをインストール

これがよくわかりませんが、国際用のアプリケーションを作成するときに使うモジュールらしい。

composerとかでもエラーが発生するので、今のうちにインストールしておく

$ brew install php56-intl

インストールしたら、php.iniに設定する

extension=intl.so

composerを使ってCakePHP3をインストール

$ composer  create-project --prefer-dist cakephp/app ${APP_NAME}

これでインストールできるはず。

ちなみに、先ほどのintlが入っていないとこうなる。

  Problem 1
    - cakephp/cakephp 3.2.8 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    - cakephp/cakephp 3.2.7 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    - cakephp/cakephp 3.2.6 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    - cakephp/cakephp 3.2.5 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    - cakephp/cakephp 3.2.4 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    - cakephp/cakephp 3.2.3 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    - cakephp/cakephp 3.2.2 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    - cakephp/cakephp 3.2.1 requires ext-intl * -> the requested PHP extension intl is missing from your system.

cakephpの設定ファイルを修正

${APP_NAME}/config/app.default.phpとなっているはずなので、app.phpにリネームする。

tmpパーミッションを変更

$ chmod -R 777 ${APP_NAME}/tmp

これでおk

f:id:aipacommander:20160710141024p:plain

【読んでいる】プログラマ脳を鍛える数学パズル

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

むずかしいれす(^q^

すごく楽しいけど、数学弱い私は何をいっているのかわからない問題が多々。。。

これを読み終えた時にはすべて理解できているであろうか。。。。

また、こんなに馬鹿だとは思っても見なかった。。。反省して毎日これを続けたいと思う。

とりあえず頭痛いからねるorz

【AngularJS1.4.x】 DirectiveからControllerのメソッドを呼ぶための設定

すごくハマりました。

やりたいこととして、とあるdirectiveからとあるcontrollerのメソッドを実行したかった。

が、方法がわからずにすごく時間がかかりました。とりあえずできたのでメモ。

環境

  • chrome 51.0.2704.103 (64-bit)
  • angularjs 1.4.9

実装

app.controller('myController', function($scope) {
    $scope.controllerMethod = funciton() {
        // controllerの処理
    };
});

app.directive('myDirective', ['$timeout', '$interval', function($timeout, $interval) {

    var getContentUrl = function() {
        return './js/template/template.html';
    };

    return {
        restrict: 'A',
        require: '?ngModel',
        scope: {
            ngModel: '=',
            ngModelDisplay: '='
        },
        templateUrl: getContentUrl(),
        controller: 'myController', // ここ大事!
        link: function(scope, element, attrs, ngModel) {
          // 省略
          scope.$apply('controllerMethod()');
        }
    }
}]);

コードの通りの実装をすればいける(はず)

directiveからcontrollerのメソッドを使う場合は、linkの中でscope.$applyにメソッド名を渡せばよい。

次に大切なことは、directiveのreturnで返すパラメータの中のcontrollerの箇所。ここをdirectiveから使用したいcontrollerのメソッドが存在するcontroller名を指定しないと使えないことがわかった。今回はこれにすごくハマりました。。。orz

仕組みはいまいちまだよくわかっていないが、とりあえずこれでできるようになりましたとさ。。。続く。

IE系のブラウザでNumber.isFinite()が動作しないので、polyfillを使おう

とあるプロジェクトで、エラーがでたのでコンソールみたら、「isFinite()って関数はありません」ってエラー。

「まじか・・・」と思いつつ、調べたら「polyfill」使えばいけるって書いている記事を見つけたのでメモ。

qiita.com

isFiniteとは?

Javascriptに実装されている関数です。有限数かどうかを確認します。

有限数とは?

有限の大きさ:ある数Nに対してそれより大きな数Mが存在する。 ということ。

よくわからんけど。無限についてはなんとなく。無限という数値は(x+1)ということができないから。それ以外は有限数と。

ようはjsで計算ミスったときによくみるInfinityがそれにあたるのかなと思いました。

developer.mozilla.org

使ってみる

動いたよ!

だがしかし。。。

> isFinite(10)
true
> isFinite('10')
true

おうおうおう(^ω^;

数値と文字列の型チェックはしてくれないのね。ということで、ドキュメントにもありますが、堅牢性の高いチェックをするならNumber.isFinite('0')を使いなさい。とのこと。

developer.mozilla.org

> Number.isFinite(10)
true
> Number.isFinite('10')
false

うむ。

しかしIEには実装されていない(´;ω;`)ブワッ

_人人人人人人人人人人人人人人人人_
Internet Explorer 未サポート<
 ̄YYYYYYYYYYYYYYYY ̄

泣いた

polyfillを使えばいける

polyfillとは?

hblog.glamenv-septzen.info

要するにHTML/JS/CSSの最新仕様や、まだドラフトとか提案段階の機能を、古いブラウザとかでも先取りして動かせるようにしてくれるライブラリをまとめて "Polyfill" というカテゴリで扱ってるらしい

ふーむ。

使ってみる

Qiitaの記事にはこう書いてある。

Number.isFinite = Number.isFinite || function(any) {
  return typeof any === 'number' && isFinite(any);
};

これでいけました!

(jsって動的にメソッドを追加できるんかいな・・・phpみたいやな)

まとめ

jsの型について知らないことが多くて困っています。。。

NaNとか一回一覧を用意して覚えたほうがいいなぁー。