Utilizing AngularJS: Establishing a Universal Parent State in UI-Router for Modals and Shared Components

In my code using UI-Router and Bootstrap-ui modal, I have defined the state as shown below. reference

var state = {
    name: 'modala',
    parent: 'home',
    onEnter: function($modal, $state) {
        modalInstance = $modal.open({
            templateUrl: 'modala.html',
            controller: 'modalaCtrl',
            controllerAs: 'modal'
        });
        modalInstance.result['finaly'](function() {
            modalInstance = null;
            if ($state.$current.name === 'modala') {
                $state.go('^');
            }
        });
    },
    onExit: function() {
        if (modalInstance) {
            modalInstance.close();
        }
    }
};

I am looking for a way to use 'modala' outside of the 'home' state.

I don't want to repeatedly define 'modala'.

Is there a method to make this work without specifying the parent every time?


Suggested Solutions:

1. Do not specify the parent in the modal state.

Result: The modal window will not be displayed within its designated parent.

Example

2. Name the modal state as ${parent.name}.modal format.

Result: This approach works, but it requires defining multiple states for each modal window and adding a state for every new parent that calls the modal.

Example

3. Define the modal state separately for each parent.

Result: Similar to pattern 2.

Example

Answer №1

There is an updated plunker available for viewing (the second attempt from the original question)

In order to showcase a different use of decorators, as explained in detail in my previous post on Stack Overflow, we will create multiple states such as 'home', 'page1', 'page2' and introduce a common child state with modal functionality.

The goal is to implement the same modal features across all child states, each belonging to a different parent. We achieve this by defining empty child states for each existing parent like so:

.config(function($stateProvider) {
  $stateProvider.state('home.generalModal',  {});
  $stateProvider.state('page1.generalModal', {});
  $stateProvider.state('page2.generalModal', {});
})

To accomplish this, we utilize a decorator in the following manner:

.config(['$stateProvider', 
  function($stateProvider) {

    var endsWith = function(stringToBesearched, valueToBeFound) {
      return stringToBesearched.slice(-valueToBeFound.length) === valueToBeFound;
    }

    $stateProvider.decorator('data', function (state, dataBuilder) {
      var data = dataBuilder(state);

      var skipState = !endsWith(state.name, ".generalModal");

      if(skipState) { 
        return data;
      }

      var modalInstance;

      var onEnter = function($modal, $state) {
          console.log("Entering state: " + $state.current.name)
          modalInstance = $modal.open({
            templateUrl:'modal.html',
            controller: 'modalCtrl',
            controllerAs: 'modalCtrl'
          });
          modalInstance.result['finally'](function() {
            modalInstance = null;
            if(endsWith($state.$current.name, ".generalModal")) {
              $state.go('^');
            }
          });
        };

      var onExit = function($state) { 
          console.log("Exiting state: " + $state.current.name)
          if (modalInstance) {
            modalInstance.close();
          }
      };

      state.self.onEnter = onEnter;
      state.self.onExit = onExit;

      return data;

    });
}])

We have extended every child state whose name ends with ".generalModal" with both onEnter and onExit functions. This centralized approach simplifies the process.

To see it in action, you can check out the updated plunker here

Answer №2

To designate a parent state for your defined child states, simply include the parent: modala property in each one.

Answer №3

In the UI-Router, there exists a solution known as the state decorator

decorator(name, func)

This feature allows us to create an aspect that can be injected into any desired state. This aspect has the ability to control common global settings such as parent or views...

For further reference, see this example here: How to decorate current state resolve function in UI-Router? Current function isn't invoked, with a small quote:

By extending (carefully) or overriding (at your own risk) the internal stateBuilder object used by $stateProvider, you can add custom functionality to ui-router, for instance deducing templateUrl based on the state name...

There is a functioning example tailored to our situation

To implement the decorator, we need to define it like so:

.config(['$stateProvider', 
  function($stateProvider) {

    $stateProvider.decorator('parent', function (state, parent) {
      // original parent created through configuration
      var result = parent(state);

      // specify states where default behavior should not be altered
      var skipState = state.name === "home" 
                   || state.name === "modala"
                      // child already inherits from parent
                   || state.name.indexOf(".") > 0 ;

      // return default if specified
      if(skipState) 
      { 
        return result;
      }

      // FINALLY - HERE
      //   modify existing parent or introduce new one 
      state.parent = 'modala'; 

      // rebuild and return modified parent
      result = parent(state);

      // new parent set successfully
      return result;

    });
}])

See this demo in action here

Answer №4

I was also eager to find the answer to this question. After some effort, I managed to figure it out.

You can check out my solution on my Stack Overflow thread

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

Issues with Await and Async functionality in Angular and Ionic 4 causing unexpected behavior

Struggling to show error messages during the sign-up process? Constantly encountering the same issue in your code? The error TS1308 is throwing you off: 'await' expression is only allowed within an async function. Take a look at this problemati ...

Troubleshooting a problem with $addToSet and $each in Mongo and Node.js

I'm facing an issue while using $addToSet to add an array of Strings to a MongoDB database. The Object setup is defined as follows: var mongoose = require('mongoose'); var Schema = mongoose.Schema; module.exports = mongoose.model('Co ...

What is the best way to choose the nearest element using the initial part of a class name?

I am working on a section of a table and need to hide a specific part when an icon is clicked. Below is the code snippet: <tr class="getmoreinfo_19"> <td>&nbsp;</td> <td colspan="3"> <div c ...

Memory usage of a Jhipster application running on an Amazon EC2 instance

My application is essentially an upscaled version of the default Jhipster app, lacking any form of cache implementation. I successfully deployed it on a t1.micro instance through Amazon's free tier option. I have been encountering sporadic 503 error ...

Steps to enable editing in an array

I'm struggling to implement an editing functionality for the lists inside the ul element in my simple to-do list project. Currently, I have the delete functionality working but need guidance on how to add an edit function. The list items are added by ...

Is there a way to add a new button each time a different model is inserted by someone?

My goal is to add a new button each time a new data for a car make is added. However, currently the button keeps getting appended to the same button instead of creating a new one. How can I ensure that a new button is created for each data entry? $.ajax ...

Error: Uncaught object in AngularJS ngRoute

I keep encountering an uncaught object error in my browser console while trying to load my AngularJS application. I am unsure if this issue is related to ng-route.js or if it's something else, as the error message only says 'uncaught object' ...

Enable direct download from external servers

I'm in search of a way to prompt a download (by right-clicking and selecting "save as") for both mp4 and flv files. The challenge is that these files are not hosted on my server, they are direct links from external websites. I have tried using .htacce ...

Javascript - Error encountered when utilizing a for loop to insert a new column into an array

I have been utilizing an API to fetch data on various stocks, and I am attempting to include a column named "symbol" with the query values using the function insertColumn. However, I am encountering an error message that says (node:15732) UnhandledPromiseR ...

The C# counterpart to the JavaScript "OR assignment" concept

Is there a comparable feature in C# to JavaScript's assignment syntax var x = y || z;? This operation does not result in true/false. If y is defined, it assigns that value to x, otherwise it assigns z to x, even if it is undefined. Keep in mind, in J ...

Unregistering an event with AngularJS

Exploring the functions of a controller named MyCtrl: class MyCtrl { constructor($scope, $rootScope, ...) { this.$scope = $scope; this.$rootScope = $rootScope; this.doThis = _debounce(this.resize.bind(this), 300); ... ...

Optimizing normals for unindexed BufferGeometry in Three.js

Currently, I am attempting to refine the normals of a mesh starting from an non indexed BufferGeometry. A similar query has been addressed in the past, however, the Three.js API has undergone significant changes since then and I am unable to make it work o ...

Utilize Content Delivery Network Components in Conjunction with a Command Line Interface Build

As we progress in building our Vue applications, we have been using the standard script tag include method for Vue. However, as we transition from jQuery/Knockout-heavy apps to more complex ones, the maintenance issues that may arise if we don't switc ...

What is the reason this JavaScript code functions properly within a <script> tag but not when placed in a separate .js

After researching various image sliders online, I came across this specific one. It worked perfectly fine when I included the JavaScript directly in a script tag within the HTML file. However, as soon as I tried to link it via a .js file, the slider stoppe ...

Creating a square shape in Twitter Bootstrap to frame an item on a webpage

I've been working on creating a webpage that looks similar to the image provided. I've managed to get about 90% of it done, but there are a couple of issues I'm facing: How can I create a square with a triangle at the bottom as shown in th ...

JavaScript and HTML are commonly used programming languages for developing

By utilizing JavaScript, I was able to generate a table dynamically based on user input. For example, if the user enters 3 and clicks "go", a table with 3 rows is created. Using the .keyup function allowed me to target a column successfully. However, an i ...

Traverse JSON object as a string

I'm new to working with JavaScript. I have a JSON string that was created using the Google Gson API, and I'm passing this string to a JavaScript function. The JSON string looks like this: '{"validationCode":"V10291","caseNumber":"2010CF1010 ...

Tips for extracting the index of the chosen item from a dropdown using ReactJs and Material UI

This is the code snippet for Dropdown component implementation: <DropDownField name={formElement.name} label={formElement.name} value={formik.values[formElement.name] || ''} dropDownItems={formElement.name === &apo ...

How can I make the arrows work on a secondary slider with EasySlider1.7?

I finally managed to get 2 sliders working on my page after reading through several other tutorials. However, I am facing an issue with the Prev & Next arrows on the second slider as they don't seem to work properly. I inherited this page from someon ...

Ways to navigate to a new webpage in JavaScript without the need to click on a link

After going through various posts and trying different methods, I am still facing challenges. In a PHP page, I have an HTML form with an onClick command that triggers a JavaScript validation procedure when the user clicks a button. While everything funct ...