(function (angular) {
    'use strict';

    angular.module('ui.tree-filter', [])
    /**
     * @ngdoc object
     * @name ui.tree-filter.provider:uiTreeFilterSettings
     */
        .provider('uiTreeFilterSettings', function () {

            var uiTreeFilterSettings = this;

            this.addresses = ['title'];
            this.regexFlags = 'gi';
            this.descendantCollection = 'items';

            this.$get = function () {
                return {
                    addresses: uiTreeFilterSettings.addresses,
                    regexFlags: uiTreeFilterSettings.regexFlags,
                    descendantCollection: uiTreeFilterSettings.descendantCollection,
                };
            };
        })
    /**
     * @ngdoc function
     * @name project.factory:projectWbsFilter
     */
        .filter('uiTreeFilter', ["uiTreeFilterSettings", function (uiTreeFilterSettings) {
            /**
             * Iterates through given collection if flag is not true and sets a flag to true on first match.
             *
             * @param {Array}   collection
             * @param {string}  pattern
             * @param {string}  address
             *
             * @returns {boolean}
             */
            function visit(collection, pattern, address) {
                collection = collection || [];
                var foundSoFar = false;

                collection.forEach(function (collectionItem) {
                    foundSoFar = foundSoFar || testForField(collectionItem, pattern, address);
                });

                return foundSoFar;
            }

            /**
             * Resolves object value from dot-delimited address.
             *
             * @param object
             * @param path
             * @returns {*}
             */
            function resolveAddress(object, path) {
                var parts = path.split('.');
                return parts.length < 2 ? object[parts[0]] : resolveAddress(object[parts[0]], parts.slice(1).join('.'));
            }

            /**
             * Checks if object or its children matches a pattern on a given field
             *
             * First it resolves the property address and gets the value.
             * If the value is a string it matches it against provided pattern.
             * If item matches because its property matches it's children are not checked.
             * Otherwise all item descendants are checked as well
             *
             * @param {Object} item
             * @param {string} pattern
             * @param {string} address property name or dot-delimited path to property.
             *
             * @returns {boolean}
             */
            function testForField(item, pattern, address) {
                var value = resolveAddress(item, address);
                var found = typeof value === 'string' ?
                    !!value.match(new RegExp(pattern, uiTreeFilterSettings.regexFlags)) :
                    false;
                return found || visit(item[uiTreeFilterSettings.descendantCollection], pattern, address);
            }

            /**
             * Checks if pattern matches any of addresses
             *
             * @param {object} item
             * @param {string} pattern
             *
             * @returns {boolean}
             */
            return function (item, pattern, addresses) {
                addresses = addresses || uiTreeFilterSettings.addresses;
                return pattern === undefined || addresses.reduce(function (foundSoFar, fieldName) {
                    return foundSoFar || testForField(item, pattern, fieldName);
                }, false);
            };
        }]);
})(angular);

@@ -1893,16 +1893,108 @@
 t('.');%0A
+%0A                if (object === undefined) %7B%0A                    return;%0A                %7D%0A%0A
         

fix demo to match latest master