Switching the templateUrl in AngularJs and accessing the model data

Currently, I am facing an issue with switching the template URL in my directive and transferring model data.

I attempted to use a function to switch the template as shown below:

.directive("sqGridData", function ($sce, $rootScope, angularProxySrv) {
   return {
   ...
    template: function (tElement, tAttrs) {
      //Not working got Exception
      //var val = $rootScope.$eval(tAttrs.sqType);

      if (tAttrs.sqType) {
         if (tAttrs.sqType === 'Iframe') {
             return '<div sq-iframe ></div>';
         }
         if (tAttrs.sqType === 'Table') {
             return '<div sq-table></div>';
         } 
      }
   },

However, this approach did not work because the value of tAttrs was an expression rather than the actual value itself like "{{item.WidgetConfig.WidgetType}}."

 <div style="height: 90%;" sq-grid-data="item.WidgetConfig" sq-type="{{item.WidgetConfig.WidgetType}}"></div>

Next, I tried using ngInclude and switching the template in the link function. The templates in the HTML are the same as above in the template function.

template: '<div ng-include="cntUrl" style="height:100%;"></div>',
link: function (scope, elem, attr) {
   var wasCalled = false;
   if (!wasCalled) {
       wasCalled = true;

      if (scope.sqGridData.WidgetType === 'Iframe') {
         scope.cntUrl = "/Templates/widget.directives.iFrame.html";
      }
      if (scope.sqGridData.WidgetType === 'Table') {
         scope.cntUrl = "/Templates/widget.directives.table.html";
      }
  }
}

While this method seems to be effective, I am now facing challenges with passing model values to my directives loaded in the include. I initially thought it could be resolved through "require":

.directive("sqIframe", function ($sce) {
    return {
        restrict: "A",
        require: "^sqGridData",
        template: '<div style="height:100%;"></div>',
        scope: {
            sqIframe: "="
        },
        link: function (scope, elem, attr, ngModel) {
              scope.cntUrl = "Home/WidgetHtmlTemplate?name=" + ngModel.HtmlTemplateName;
               scope.IframeUrl = $sce.trustAsResourceUrl(ngModel.WidgetName);;
            }
        }
    }
})

Unfortunately, I encountered an error stating that the controller "sqGridData" could not be found. Is there a more efficient way to address this issue or does anyone have insights on where I might be going wrong?

Answer №1

A simple solution to this problem involves using a directive that switches templates based on an attribute value, along with a scope that passes a generic model value. The ng-switch is utilized in the HTML where the directive is called, not within the directive itself.

In your HTML code, you can switch based on the type of item, with the "-when" specifying the value of the type.

<div ng-switch="item.WidgetConfig.WidgetType">
    <div ng-switch-when="Iframe">>
         <div sq-grid-data template="Iframe" modelvalue="item.WidgetConfig"></div>
    </div>
    <div ng-switch-when="Table">>
         <div sq-grid-data template="Table" modelvalue="item.WidgetConfig"></div>
    </div>
</div>

The directive would be structured like this...

.directive('sqGridData', function () {
    // Returns the desired template based on the 'template' attribute value
    return {
        restrict: 'EA',
        replace: true,
        scope: {
            modelval: '=modelvalue'
        },
        templateUrl: function (elem, attr) {
            switch (attr.template) {
                case 'Iframe':
                    return "/Templates/widget.directives.iFrame.html";
                case 'Table':
                    return "/Templates/widget.directives.table.html";
                default:
                    return null;
            }                
        }
    };
});

Alternatively, if you prefer a shorter and less flexible approach, where the template names match the types directly, you could simplify it like this...

templateUrl: function (elem, attr) { return '/Templates/widget.directives.' + attr.template + '.html"; }

Remember to use the generic name for the scope value in both templates to access the necessary data passed to the directive's isolated scope.

<div>
     <span>{{ modelval.imaStringPropertyOnTheItemWidgetConfig }} </span>
</div>

With everything set up correctly, your templates will work effectively with the directive.

Answer №2

I have successfully resolved my issue.

Utilizing the following Directive:

<div style="height: 90%;" sq-grid-data="item.WidgetConfig"></div>

A directive that enables switching between templates and directives

angular.module("widget.directives", ["angularProxySrv"])
    .directive("sqGridData", function () {
        return {
          restrict: 'A',
          template: '<div ng-include="cntUrl" style="height:100%;"></div>',
          scope: {
              sqGridData: "="
          },
          link: function (scope, elem, attr) {
              scope.sqGridData = scope.sqGridData;

              if (scope.sqGridData.WidgetType === 'Iframe') {
                  scope.cntUrl = "Templates/widget.directives.iFrame.html";
              }

              if (scope.sqGridData.WidgetType === 'Table') {
                  scope.cntUrl = "Templates/widget.directives.table.html";
              }
          }
      }
  })

I need to define the

scope.sqGridData = scope.sqGridData;

It's uncertain if there is a more optimal solution available, but I found this to be the only way to access the scope property from the child directive using scope.$parent - Is there perhaps a better alternative (I attempted to utilize the require property but it was not successful)?

The content of the Templates for "widget.directives.iFrame.html"

 <div sq-iframe></div>

The content of the Templates for "widget.directives.table.html"

<div sq-table></div>

The Directive for the sqTable

.directive("sqTable", function (angularProxySrv) {
    return {
          restrict: "A",
          replace: true,
          template: '<div ng-include="cntUrl" style="height:100%;"></div>',
          scope: true,
          link: function (scope, elem, attr, ngModel) {
              scope.cntUrl = "Home/WidgetHtmlTemplate?name=" + scope.$parent.sqGridData.HtmlTemplateName;
              angularProxySrv.LoadWidgetDataByWidgetName(scope.$parent.sqGridData.WidgetName).then(function (data) {
              scope.Data = data;
          });
        }
      }
    })

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

Utilize Javascript to input text into a webform

I am working on creating a bot that simulates user input for the WattsApp web website. When I manually type a message into the website, it enables a button that allows me to send the message. However, when my script runs, it finds the input box, changes t ...

Setting the state variable value asynchronously using AngularJS UI-If

Is it possible to limit access to the sidebar until the user has completed the login process? The sidebar is located outside the main ui-view section I am assuming that authenticated is a state variable <div ng-controller="MyController" ui-prevent-to ...

Is there a way to incorporate a subtle fading effect when transitioning between images?

I find this continuously changing image every 5 seconds to be a bit overwhelming without any smooth transition. Is there a way I can implement a short fade effect like what is possible in CSS? import React, { useEffect, useState } from "react"; ...

Explore the scope of each item in ng-repeat

My table has rows that use their respective scope variables for conditional rendering: <tr ng-repeat="row in data"> <input type="text" data-ng-show="editMode" data-ng-model="row.smth"/> The input is only shown when the row's scope vari ...

Interactive sidebar scrolling feature linked with the main content area

I am working with a layout that uses flexboxes for structure. Both the fixed sidebar and main container have scroll functionality. However, I have encountered an issue where scrolling in the sidebar causes the scroll in the main container to activate whe ...

Validating Password Consistency using Javascript

I'm having trouble with validating the password fields and ensuring they match, even when both input boxes contain the same password. JavaScript var validator = $("#signupform").validate({ rules: { password: { required: true, minle ...

Protractor - Issue with Page Object not reflecting changes in DOM elements

Currently, I am conducting testing on a Single Page Application created with angular.js. For test writing, I am following the Page Objects pattern. Within this application, there are several lists that undergo updates. For instance, there is a list of atta ...

Utilizing sub-function within ControllerAs in AngularJS

Greetings! I am a newcomer to AngularJS and I've been using the controlleras style in AngularJS as it makes the code more presentable and clean. However, I'm facing an issue when trying to call a subfunction in my controller. Here's a snippe ...

Retrieve the complete HTML content of a webpage, including the values of all input fields

I'm attempting to save the entire webpage as an HTML file, including all previously entered values in input fields. I have already tried this method: $("#content").html(); However, it does not retain the values entered into input fields. $("#conten ...

Unable to download and install jspdf version 1.5.3

Currently, I am facing an issue where I need to convert HTML to PDF using jspdf 1.5.2. However, I am encountering an error that says "Cannot read property 'charAt' of undefined" when trying to utilize html2canvas. When attempting to upgrade to j ...

When navigating back from a child route in history mode, the component is erroneously mounted twice

I have encountered an issue while using vue-router in history mode. When I am on the child route "/dashboard" and refresh the page, the <ccp/> component seems to be mounted twice. The ccp component has console logging in both the created and mounted ...

Error message: Property is not found in the $rootScope object in AngularJS

Encountering an issue while attempting to assign a value to the rootscope in Typescript. class TestClass{ this.rootScope: ng.IRootScopeService; constructor($rootScope){ this.rootScope = $rootScope; } addValueToRoot=()=>{ ...

How to show a div for small screens only using Bootstrap 4 beta?

Previously, in Bootstrap alpha 6 I was able to achieve this by writing the following code for displaying a div's contents only for sm: <div class="hidden-md-up hidden-xs-down"> This content would only be visible for sm in Bootstrap 4 alpha 6 ...

Error message encountered when deploying a Discord bot on Heroku: "SyntaxError: Unexpected token '??='"

I encountered an issue when trying to deploy a Discord bot that I created using Node.js on Heroku. The error message is as follows: 2021-11-05T00:00:10.334347+00:00 app[web.1]: > node . 2021-11-05T00:00:10.334348+00:00 app[web.1]: 2021-11-05T00:00:10.3 ...

Customize the header toolbar title in FullCalendar

I am using a basic fullcalendar with buttons in the headerToolbar My question is, how do I customize the titles on these buttons? https://i.sstatic.net/xAgXG.png https://i.sstatic.net/wK5IX.png For example, instead of month view I'd like it to be j ...

Navigate Formik Fields on a Map

Material UI text-fields are being used and validated with Formik. I am looking for a way to map items to avoid repetitive typing, but encountering difficulties in doing so. return ( <div> <Formik initialValues={{ email: '&a ...

Is there a way for the window.onbeforeunload event to wait for an ongoing animation to finish

Exploring the JavaScript code below which utilizes an animation library (such as scriptaculous). window.onbeforeunload = function(event) { document.body.fade(); } When leaving the page, the animation does not finish before the page changes. This raise ...

AngularJS faces an issue where it cannot recognize the selected option if the options set is modified using jQuery

Within an AngularJS (v1.4.14) app containing legacy code, there is a web form that includes the following select tag: <select id="selectCourses" class="input-select" data-ng-model="fields.course" data-courses="form.cou ...

What could be causing my React button to stop functioning as a link to an external website when using anchor tags?

I recently created some buttons for my website using React. Initially, everything was working perfectly with the buttons, but suddenly they stopped functioning. Strangely, I didn't make any alterations to the code and I'm puzzled as to why they a ...

Retrieving values from all fields in a dynamic form using VuejsLet's say

In the process of developing an admin panel using Vuejs and tailwind CSS for managing exercises on a page, I have encountered some challenges. My current objective is to insert the dynamic form values into a Firebase real-time database. However, I am stru ...