Search code examples
jsonangularjsangular-strapng-submit

How do I update the model on click only (angular-strap typeahead and json)


I'm having trouble figuring out how to have dynamic data only update when the user selects from the typeahead menu or clicks the search button.

Right now, the dynamic content pertaining to the search query updates automatically when the input value is changed (content disappears). I want the content to stay in view until a new selection has been either clicked in the typeahead list or clicked by the search button.

Any insight at all would be greatly appreciated! Thank you!

Plunker demo:

http://plnkr.co/edit/jVmHwIwJ0KOKCnX6QjVa?p=preview

Code:

<!-- HTML -->
  <body ng-controller="MainController">

<!-- Search -->
<div class="well">
  <p>Search the term "content"</p>
  <form role="form">
    <div class="form-group clearfix search">
      <input type="text" ng-model="selectedContent" ng-options="query as query.searchQuery for query in searchData" bs-typeahead="bs-typeahead" class="form-control search-field"/>
      <button type="button" class="btn btn-primary search-btn"><span class="glyphicon glyphicon-search"></span></button>
    </div>
  </form>
</div>

<!-- Dynamic Content -->
<div class="well">
  <h4>{{ selectedContent.contentTitle }}</h4>
  <ul>
    <li ng-repeat="item in selectedContent.headlines">{{item.headline}}</li>
  </ul>
</div>

<!-- typeahead template -->
<ul class="typeahead dropdown-menu" tabindex="-1" ng-show="$isVisible()" role="select">
<li role="presentation" ng-repeat="match in $matches" ng-class="{active: $index == $activeIndex}">
  <a href="" role="menuitem" tabindex="-1" ng-click="$select($index, $event)" ng-bind="match.label"></a>
</li>

<!-- JS -->
var app = angular.module('demoApp', ['ngAnimate', 'ngSanitize', 'mgcrea.ngStrap'])
.config(function ($typeaheadProvider) {
  angular.extend($typeaheadProvider.defaults, {
    template: 'ngstrapTypeahead.html',
    container: 'body'
   });
});

function MainController($scope, $templateCache, $http) {

  $scope.selectedContent = '';

  $http.get('searchData.json').then(function(response){
    $scope.searchData = response.data;
    return $scope.searchData;
  });

};

Solution

  • You could use a directive such as this:

    app.directive('mySearch', function(){
      return {
        restrict: 'A',
        require: 'ngModel',
        link: function($scope, $element, $attrs, ngModel){
          ngModel.$render = function(){
             if (angular.isObject($scope.selectedContent)) {
               $scope.clickedContent = $scope.selectedContent;
             }
          }
           $scope.updateModel = function() {
             $scope.clickedContent = $scope.selectedContent;
          }
        }
      }
    
    })
    

    plunker

    Edit:

    I added using the ngModelController. The function you set ngModel.$render to gets called whenever the model updates. If you click the typahead popup, then the model selectedContent will be an object, otherwise it'll be a string. If it's an object (meaning the user clicked the typahead popup) we do the same as we did in the updateModel function.