Search code examples
htmlangularjsangular-ui-bootstrapangular-ui-typeahead

Angular UI-Bootstrap typeahead in table


Simple question really, but how can I setup the typeahead to work in a table that works off of a different table than my typeahead?

For Example, I have a foreign key in a table and I want to let the users select this key based on the respective NAME value in the foreign key's primary table.

Code Example:

 <table class="table table-bordered table-hover table-striped rwd-table" id="page-wrap">
<thead>
    <tr>
        <th>Primary ID</th>
        <th>Foreign Key (As Name)</th>
    </tr>
</thead>
<tbody>
    <tr ng-repeat="p in PrimaryTable" id="display">
        <td data-th="ID">{{p.PrimaryID}}</td>
        <td>
            <input id="ForeignKeyName"
                   type="text"
                   ng-model="p.ForeignKeyID"
                   uib-typeahead="f.ForeignKeyID as f.ForeignKeyName for f in ForeignKeyTable | filter:$viewValue"                               
                   class="form-control">
        </td>                   
    </tr>
</tbody>

With this example, I would want the users to see the "Foreign Key (As Name)" As the Name value instead of the ID value. The trick is that I also want the underlying value to be the ID and have it mapped to match the original value, as notified by the ng-model.

UPDATE: Another question I had that was in line with the previous one is how do I setup my ng-model to show the ForeignKeyTable.ForeignKeyName in place of the PrimaryTable.ForeignKeyID?

This would be similar ( I imagine) to how the uib-typeahead matches the ForeignKeyTable.ForeignKeyID and ForeignKeyTable.ForeignKeyName but with the two seperate tables?

What I would desire is to be able to put ng-model: PrimaryTable.ForeignKeyID as ForeignKeyTable.ForeignKeyName


Solution

  • First thing would be updating PrimaryKeyTable rows every time user selects value in typeahead. You'll have to catch selected item and manually assign its ForeignKeyId value to the row of PrimaryTable. The way to do it is to add typeahead-on-select directive to your typeahead and bind it to the function that assigns the values for you.

    It would look like this:

    HTML

    <tr ng-repeat="p in PrimaryTable" id="display">
        <td data-th="ID">{{p.PrimaryID}}</td>
        <td>
            <input id="ForeignKeyName"
                       type="text"
                       ng-model="selectedItem" <!-- could be anything really for we will not use it here -->
                       uib-typeahead="f.ForeignKeyID as f.ForeignKeyName for f in ForeignKeyTable | filter:$viewValue"   
                       typeahead-on-select="onSelect($item, $model, $label, p)"                            
                       class="form-control">
        </td>                   
    </tr>
    

    Inside your controller

    $scope.onSelect = function($item, $model, $label, primaryKeyTableRow) {
        primaryKeyTableRow.ForeignKeyId = $item.ForeignKeyId;
    }
    

    Next step is to display name property value of ForeignKeyTable row that corresponds to ForeignKeyId from PrimaryKeyTable in each row. Since we have to filter ForeignKeyTable to find suitable item it would be a good idea to put that logic inside the controller. For there are multiple rows in which we want to display corresponding name, we'll have to filter the ForeignKeyTable for each row separately. This is where ng-controller for ng-repeat comes in handy. What we'll do is bind new controller for each table row generated by ng-repeat and put some logic inside that controller. In HTML it would look like this:

    <tr ng-repeat="p in primaryKeyTable" ng-controller="itemController">
        <!-- ... -->
    </tr>
    

    And we'll have to define new controller in JS file:

    app.controller('itemController', function() {
        // ...
    });
    

    Now we can have separate logic for each row in the table. So that's a place to filter ForeignKeyTable to find corresponding item and display it's name.

    Since whole code is kind of big I've put it in the plunker: http://plnkr.co/edit/xccgnpxoPHg6vhXWPwZn?p=preview

    See what you can do with it.