8

I'm using Angular Material component "md-autocomplete" in my project.

We are trying to render dynamic response that we are getting from "md-list" component's item-click's event call.

Issue: However, before the event call is invoked, md-autocomplete method is invoked.

My Requirement: Is there a way to invoke the event call before invoking md-autocomplete method.

Here we attached sample images, that show's you basic response what we need as output.

object 1 related response

object 2 related response

I tried below code, But it is not working. I need solution for the problem.

HTML Source Code:

md-list code

<md-list>
    <div ng-repeat="object in ['object 1', 'object 2', 'object 3', 'object 4', 'object 5', 'object 6'] track by $index">
        <md-list-item class="md-2-line contact-item" ng-click="listItemClick($event, object)">
            <div class="md-list-item-text compact">
                <h3>Object data displayed here like object 1, object 2 and etc ...</h3>
            </div>
        </md-list-item>
    </div>
</md-list>

md-autocomplete code :

<md-autocomplete
        ng-disabled="isDisabled"
        md-no-cache="noCache"
        md-selected-item="selectedItem"
        md-search-text-change="searchTextChangeEvent(searchText)"
        md-search-text="searchText"
        md-selected-item-change="selectedItemChangeEvent(item)"
        md-items="item in search(searchText)"
        md-item-text="item.id"
        md-min-length="0"
        placeholder="Search by id ..."
        md-menu-class="autocomplete-custom-template">
        <md-item-template>
            <span class="item-title">
                {{id}}
            </span>
        </md-item-template>
</md-autocomplete>

AngularJS Script Code :

(function() {

        var app = angular.module('module-name');

        var controller = function($scope, $rootScope,$http, $timeout, $q, $log) {

            var self = this;

            self.simulateQuery = false;
            self.isDisabled    = false;

            $rootScope.objectName = "object 1";

            self.response = loadValues($rootScope.objectName);
            self.search = search;
            self.selectedItemChangeEvent = selectedItemChangeEvent;
            self.searchTextChangeEvent = searchTextChangeEvent;

            // ******************************
            // Internal methods
            // ******************************

            /**
             * Search for repos... use $timeout to simulate
             * remote dataservice call.
             */
            function search (query) {

                var results = query ? self.response.filter( createQueryFilterFor(query) ) : self.response,
                  deferred;
                if (self.simulateQuery) {
                    deferred = $q.defer();
                    $timeout(function () { deferred.resolve( results ); }, Math.random() * 1000, false);
                    return deferred.promise;
                } else {
                    return results;
                }
            }

            function searchTextChangeEvent(text) {
              $log.info('Text changed to ' + text);
            }

            function selectedItemChangeEvent(item) {
                $log.info('Item changed to ' + JSON.stringify(item));
            }

            /**
             * Build `components` list of key/value pairs
             */
            function loadValues(name) {

                var dynamicData = '';

                if(name === "object 1") {
                    dynamicData = [{
                        "id": 1,
                        "name": "some name here"
                    },{
                        "id": 2,
                        "name": "some name here"
                    }];
                } else if(name === "object 2") {
                    dynamicData = [{
                        "id": 3,
                        "name": "some name here"
                    },{
                        "id": 4,
                        "name": "some name here"
                    }];
                } else if(name === "object 3") {
                    dynamicData = [{
                        "id": 5,
                        "name": "some name here"
                    },{
                        "id": 6,
                        "name": "some name here"
                    }];
                }

                return dynamicData.map( function (response) {
                    response.value = response.id.toLowerCase();
                    return response;
                });
            }

            /**
             * Create filter function for a query string
             */
            function createQueryFilterFor(query) {

              var lowercaseQuery = angular.lowercase(query);

              return function filterFn(item) {
                return (item.value.indexOf(lowercaseQuery) === 0);
              };
            }


            $scope.listItemClick = function(event, object) {

                $rootScope.objectName= object.someFiledName; // It will give md-list-item name (like object 1 or object 2 and etc ...)

                self.response = loadValues($rootScope.name);
            }
        };

        app.controller("controller", controller)
    }());
Fares M.
  • 1,538
  • 1
  • 17
  • 18

2 Answers2

3

I have taken your code and created a plunkr demo. I tweaked it few places, please feel free to explore the code in plunkr. Now suggestions are loading according to object selected.

I think filter logic was not correct according to use case you mentioned here so I corrected createQueryFilterFor function logic. I made changes in md-item-template section too.

function createQueryFilterFor(query) {
      var lowercaseQuery = angular.lowercase(query);
      return function filterFn(item) {
        //below condition updated to match search id
        return (item.value.toString() === lowercaseQuery);
      };
    }

see demo

Raj
  • 3,890
  • 7
  • 52
  • 80
  • 1
    You can search by id, refer `loadValues` function for id and respective values. As per question, that is the expected behavior. – Raj Apr 03 '17 at 13:14
  • 1
    the problem seems to be this - when you click on auto complete field, the elements inside md-list (buttons), are no longer accessible. If you try hovering, on the md-list with the auto-complete drop down showing, you will see that hovering doesn't change the background on the list element like it usually would. Now, this results in the behavior where the user has to click twice - once to get out of the auto complete field and the second to make the list item selected. – Jay Apr 04 '17 at 10:57
2

I've fixed some issues in your code and corrected the hovering and double-clicking issue as per your comment in another answer.

Here's your updated code: http://codepen.io/anon/pen/ryXyxj

Note to communicate between controllers it is considered better practise to use a shared service rather than setting values on the $rootScope:

app.controller('mainController', function($scope, menuSelection) {
  $scope.menuSelection = menuSelection; // retrieve settings object from service method and bring into scope
  // now whenever one sets $scope.menuSelection.selected = "object 2", it will update the value in the other controller as well (and vice-versa)
});

app.controller('secondController', function($scope, menuSelection) {
  $scope.menuSelection = menuSelection; // retrieve settings object from service method and bring into scope
});

app.factory('menuSelection', function() {
  var settings = {};
  settings.selected = 'Object 1';  // default
  return settings;
});

You can find a demo of 2 controllers communicating via a service here: https://stackoverflow.com/a/42408380/1544886

Community
  • 1
  • 1
K Scandrett
  • 16,390
  • 4
  • 40
  • 65