Add the "multiple" attribute to ui-select only if certain conditions are met

I am attempting to dynamically add the multiple attribute to a ui-select directive based on the value of a specific property by using the ng-attr- directive. Unfortunately, this method is not functioning as expected in my case. To better illustrate the issue I am facing, I have created a Plunker example.

View Plunker Example

Answer №1

Modifying Directives

After extensive research and review of the relevant GitHub Issue in the Angular Repo, I have successfully implemented a directive solution to address the issue at hand.

The key steps involved setting up a directive with a higher priority and utilizing the terminal attribute set to true. This approach effectively skips the compilation of all other directives after our directive is compiled. Additionally, within the postLink function, the entire element itself is compiled. It is crucial to remove our own directive beforehand to prevent an infinite loop from occurring.

A special recognition goes out to the insightful advice provided on Adding directives from directive in AngularJS

Custom Directive Implementation

angular.module('app')
  .directive('multiSelectChecker', function ($compile) {
    return {
      restrict: 'A',
      replace: false, 
      terminal: true, // Set directive compilation only
      priority: 50000, // Higher priority for early compilation
      compile: function(element, attrs) {
        element.removeAttr("multi-select-checker"); // Remove directive attributes to avoid infinite loop
        element.removeAttr("data-multi-select-checker"); // Also remove data-prefixed attribute if present

        return {
          pre: function(scope, iElement, iAttrs, controller) {  },
          post: function(scope, iElement, iAttrs, controller) { 
            if (scope.options.Multiple === true) {
              iElement[0].setAttribute('multiple', ''); // Setting multiple directive using vanilla JS method
            }
            $compile(iElement)(scope);
          }
        };
      }
    };
  });

HTML Markup

<ui-select ng-model="model.choice" multi-select-checker>
    <ui-select-match>{{$item.Title}}</ui-select-match>
    <ui-select-choices repeat="item.Id as item in options.SuggestedValues | filter: { Title: $select.search }">
      <div ng-bind="item.Title | highlight: $select.search"></div>
    </ui-select-choices>
  </ui-select>

Functional Plnkr Example:

Live Demo Link showcasing the directive functionality


Alternate Approach Utilizing Wrapping Directive

In exploring alternative solutions, I devised the following approach:

  1. Introduction of a wrapping directive named multi-select-checker
  2. Within this directive, validation of options.Multiple value
  3. Provision of distinct template URLs based on the outcome: Case 1): single-select.tpl.html or Case 2): multi-select.tpl.html containing the necessary 'multiple' directive

Directive Declaration:

app.directive('multiSelectChecker', function() {
return {
    template: '<ng-include src="getTemplateUrl()"/>',
    controller: function($scope) {
      $scope.getTemplateUrl = function() {
        if ($scope.options.Multiple === true) {
          console.log("multi-select");
          return "multi-select.tpl.html"
        }
        else {
          console.log("single select");
          return "single-select.tpl.html"
        }
      }
    }
  }
})

Integration in HTML:

<body ng-controller="DemoCtrl">
  <multi-select-checker>
  </multi-select-checker>
</body>

Single Select Template:

<ui-select ng-model="model.choice">
    <ui-select-match>{{$item.Title}}</ui-select-match>
    <ui-select-choices repeat="item.Id as item in options.SuggestedValues | filter: { Title: $select.search }">
        <div ng-bind="item.Title | highlight: $select.search"></div>
    </ui-select-choices>
</ui-select>

Multi-Select Template:

<ui-select ng-model="model.choice" multiple>
    <ui-select-match>{{$item.Title}}</ui-select-match>
    <ui-select-choices repeat="item.Id as item in options.SuggestedValues | filter: { Title: $select.search }">
        <div ng-bind="item.Title | highlight: $select.search"></div>
    </ui-select-choices>
</ui-select>

It is evident that these templates primarily differ in incorporating the 'multiple' directive. There may exist more efficient resolutions to this issue.

I find it puzzling why the ng-attr-multiple approach fails to deliver the expected results.

Furthermore, upon inspection, it was noted that two separate input fields are rendered when employing the ng-attr-multiple technique.

Moreover, the single selection scenario appears to be disrupted by eliminating the multiple directive - a similar observation made in the initial Plnkr provided.

Tested and Verified Code

To witness the functioning implementation, refer to this working example on Plnkr: Interactive Preview of the revised approach

Answer №2

Are you aiming for this particular outcome?

<body ng-controller="DemoCtrl">
    This section is functioning perfectly:
    <ui-select ng-model="model.choice" multiple>
        <ui-select-match>{{$item.Title}}</ui-select-match>
        <ui-select-choices repeat="item.Id as item in options.SuggestedValues | filter: { Title: $select.search }">
            <div ng-bind="item.Title | highlight: $select.search"></div>
        </ui-select-choices>
    </ui-select>
    <br />
    <br />
    However, this part is not working as expected:
    <ui-select ng-model="model.choice2" multiple="{{options.Multiple}}">
        <ui-select-match>{{$item.Title}}</ui-select-match>
        <ui-select-choices repeat="item.Id as item in options.SuggestedValues | filter: { Title: $select.search }">
            <div ng-bind="item.Title | highlight: $select.search"></div>
        </ui-select-choices>
    </ui-select>
  </body>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on customizing image borders/masks with hover effects

Is there a React library or a simple CSS trick to create an image's canvas cropping effect on hover? For example, similar to this: Thanks in advance! ...

The error message "element.getAttribute is not defined" is common when using the Perfect

I'm facing an issue while trying to implement the perfect-scrollbar plugin on my AngularJS website. The error I encounter is as follows: TypeError: element.getAttribute is not a function at getId (http://localhost/Myproject/js/lib/perfect-scrollb ...

How to successfully load the google-map-react library

After installing the google-map-react library locally in my app, I verified that it is listed in my package.json under dependencies. The corresponding folder also exists in the node_modules directory. However, when attempting to reference the component con ...

What is causing the issue with the code `exports = { z: function() {} };` not functioning as intended?

Script A exports = { z: function() { console.log('aZ'); } }; Script Main require('./a').z(); // error Have you ever wondered why require('./a') ends up returning an empty object? ...

Is the each() method in jQuery essentially a for loop?

Experimenting with adding a serialized class to a group of objects, I attempted the following approach: jQuery('#preload img').each(function(){ jQuery('#thumbs').append('<img class="index' + index + '" src="&apos ...

Content OverFlow: DropDown Menu is not overlapping the content, but rather pushing it downwards

In my webpage, I have a drop-down menu that traditionally pushes the content below it down to make space for its items. However, I want the drop-down to overlap the contents below without affecting their position. I've tried various solutions, such a ...

Passing data to an Angular directive

I am facing an issue while trying to pass information through a view in a directive. Despite binding the scope, I keep seeing the string value 'site._id' instead of the actual value. Below is the code for the directive: angular.module('app ...

Find a specific row in a table using jQuery without requiring any input from the

I want to create a search function that filters results in a table based on user input. The script I have currently works but I need it to only search the first column without requiring the user to click an input field. I want the default value to load whe ...

What is the best way to send an inline SVG string to my controller?

I am trying to send an inline svg string along with some other properties to my controller. When I replace the svg string with a normal string like "blabla", it successfully reaches my controller. However, with the actual svg string, it never makes it to ...

Where does the browser retrieve the source files for "sourcemapped" JavaScript files from?

As I begin working on an existing project built with angular JS, upon opening chrome dev tools and navigating to the "source" view, a message appears: Source map detected... This prompts me to see a link to: https://i.stack.imgur.com/RZKcq.png The fi ...

adding a touch of flair to a form input that doesn't quite meet the

My goal is to have a red background appear when an input is invalid upon form submission. I attempted the following code: input:invalid { background-color:red; } While this solution worked, it caused the red background to show up as soon as the page l ...

How can I use JavaScript and HTML to print a canvas that is not within the print boundaries?

As someone who is new to javascript, I recently created a canvas function that allows me to successfully print. However, I am encountering an issue with printing large canvas areas. When I navigate to the further regions of the canvas and try to print, i ...

What are the appropriate scenarios to utilize the declare keyword in TypeScript?

What is the necessity of using declare in TypeScript for declaring variables and functions, and when is it not required? For instance, why use declare var foo: number; when let foo: number; seems to achieve the same result (declaring a variable named ...

Encountered an error while trying to retrieve data from

Having trouble with file uploads to the S3 bucket using @aws-sdk/client-s3 library and encountering errors when uploading files larger than 70kbps: `TypeError: Failed to fetch at FetchHttpHandler.handle (fetch-http-handler.js:56:13) at PutObjectCommand ...

Building a local database using the MVC framework concept

Can a locally stored database be developed using MVC framework principles in javascript and html5? Thank you Ravindran ...

Ways to properly exit a function

What is the best way to pass the apiKey from the createUser function in User.ts to Test.ts in my specific scenario? User.ts interface User { url: string, name: string, } class User{ async createUser( user: User ):Promise<void> { le ...

Navigating with useRouter().push() from the "next/navigation" package is not functioning as expected when used on a customized signIn page alongside next-auth

Upon logging in successfully on my custom signIn-Page using next-auth, I am facing an issue with redirecting back to the callbackUrl. The setup includes react 18.2.0, next 13.4.8-canary.2, and next-auth 4.22.1. The code for the signIn-Page (\src&bsol ...

Utilize JavaScript to submit the FORM and initiate the 'submit' Event

Hey there! Here's the code I've been working on: HTML : <html> <body> <form enctype="multipart/form-data" method="post" name="image"> <input onchange="test();" ...

Ensure the http request is finished before loading the template

When my template loads first, the http request is fired. Because of this, when I load the page for the first time, it shows a 404 image src not found error in the console. However, after a few milliseconds, the data successfully loads. After researching a ...

404 Response Generated by Express Routes

Exploring the MEAN stack has been a great way for me to expand my knowledge of node and express. Currently, I am working on creating a simple link between two static pages within the app. My routes are set up as follows: //Home route var index = require( ...