Updating a URL once AngularJS has finished processing it

Currently, I am utilizing Primo, an AngularJS app developed by Ex Libris. This application functions as a library catalog, enabling users to explore both physical and digital collections within the library. Despite not having direct access to the original AngularJS codebase, I do possess the capability to define and append AngularJS modules as needed.

My immediate task seems straightforward at first glance: establish a link within Primo that directs users to a third-party app, inclusive of a query string encompassing the specific item ID which the patron is viewing, for example,

https://library.example.edu/ill/primo.php?docID=cdi_proquest_ebookcentral_EBC7007769
.

By using the Primo control panel, I was able to successfully insert the link with options to set the URL, link text, and other parameters. The screenshot below illustrates this section of the control panel:

The URL Template field permits the input of the desired link URL and offers placeholders to incorporate data related to the item. For instance, {rft.atitle} would be substituted with the article title. Regrettably, it lacks a method to insert the docID directly. Although I attempted including an AngularJS token like {{pnx.control.recordid[0]}}, presumably to fetch the required data, the UI rejected this input as an invalid parameter. Consequently, I specified my URL as

https://example.com/incoming.php?docID=replaceMe
. My intention was to craft JavaScript logic to extract the docID from the dynamic URL and update the link prior to user interaction.

However, upon implementation, Primo generated the link as an AngularJS component, generating the following code snippet when rendered on an actual page:

<md-list-item ng-repeat="service in $ctrl.filteredServices() track by $index" role="listitem">
    <button type="button" ng-transclude="" (click)="$ctrl.onClick(service)" aria-label="Interlibrary Loan, opens in a new window">
        <span ng-if="service['service-type'] === 'OvL'">
            <a
                ng-href="https://library.example.edu/ill/primo.php?docID=replaceMe"
                ng-click="$event.preventDefault()"
                translate="Interlibrary Loan"
                href="https://library.example.edu/ill/primo.php?docID=replaceMe"
            >Interlibrary Loan</a>
        </span>
    </button>
</md-list-item>

To enhance clarity, extraneous container DIVs and styling information have been excluded. Moreover, the indentation has been refined for readability.

Evidently, the link incorporates both an ng-href attribute and an href attribute storing the initial URL inputted. Despite attempting to dynamically update these attributes via Javascript manipulation, the modifications failed to persist when clicking the link, subsequently redirecting users to the unaltered URL. Supposedly, AngularJS retains the original URL within its internal data structure during processing, thereby circumventing any alterations made to the corresponding tag attributes.

Notably, a redundant <button> encompassing the link was introduced, effectively replicating the functionality of the link itself. While this design choice appears aimed at expanding the clickable area, managing the URL updates across both elements complicates the debugging process.

In essence, my goal centers around substituting the placeholder "replaceMe" with the actual docID and updating the associated URL accordingly. Although a pragmatic solution could involve manipulating the DOM to replicate and replace the entire HTML structure produced by AngularJS, such brute force tactics contradict my preference of collaborating harmoniously with AngularJS rather than working against its innate functionalities.

This predicament raises two pivotal inquiries:

  1. How can I pinpoint where AngularJS stores the URL? Identifying the exact location of this data remains elusive.
  2. Once located, is there an AngularJS-specific approach to modifying it? Adhering to AngularJS conventions is imperative to avoid unforeseen conflicts.

After exhaustively scouring through search results predominantly yielding AngularJS coding resources instead of practical insights on real-time data updates, my continuous efforts over the past three days have yet to yield substantial progress. Your guidance or assistance would be immensely valued and appreciated.

UPDATE, six days later:

Progress is being made, albeit at a gradual pace.

An initial hurdle encountered involved the discovery that debug info had been disabled by the original developers at Ex Libris:

$compileProvider.debugInfoEnabled(false)

Further exploration led me to stumble upon a Firefox extension titled AngularScope, promising the ability to inspect scopes linked to arbitrary DOM elements. Upon installation, the extension alerted me regarding the disabled debug info, prompting me to re-enable it via the console with:

angular.reloadWithDebugInfo()

Discovering that the scope for my current link contains an object referred to as service housing a property named

link-to-service</code shed light on where the URL data was stored. Subsequently, I captured a reference to the target link under investigation denoted as <code>myLink
and formulated the following script:

angular.element(myLink).scope().$apply(function () {
    angular.element(myLink).scope().service["link-to-service"] = newURL;
});

Remarkably, the execution yielded successful outcomes! Updating the URL content, users are now directed to the correct destination by clicking either the link or accompanying button.

However, a crucial caveat emerged - this method exclusively operates when AngularJS's debug info feature is enabled. By default, this option remains inactive, causing the AngularJS scopes to remain detached from the DOM, rendering angular.element(myLink).scope() inaccessible and ineffectual.

An attempt to restore access to the scopes by executing the following script methodology provided limited success:

var scope;
angular.element(document.body).injector().invoke(function ($rootScope) {
    scope = $rootScope;
    console.log(scope);
});

Unfortunately, encountering a similar setback where

angular.element(document.body).injector()
returned as undefined suggests potential revisions to AngularJS framework may have transpired since the referenced answer back in 2015.

A strategic maneuver entailing the establishment of a novel AngularJS module integrated with its .run() function to interact with the DOM post-AngularJS bootstrap phase but premised before template compilation had little to no impact, likely due to delayed loading subsequent to page initialization by the time my module integration took effect.

Contemplation ensued surrounding leveraging event handling mechanisms like DOMContentLoaded to preemptively modify URLs ahead of AngularJS script injection. Realization dawned upon realizing the counterproductive nature of such attempts given my scripts were appended by AngularJS itself; essentially translating to missed opportunities for timely intervention towards URL updates.

Hence, the focal issue stands resolute: How does one obtain access to an AngularJS component's scope sans debug info?

If empowered with scope accessibility, the URL update procedure becomes trivial. Alas, despite laboring intensively over the course of nine days, achieving this objective persists as an ongoing challenge. A growing temptation lingers urging one towards devising a potential workaround involving radical JavaScript interventions aimed at reconstructing the AngularJS-generated HTML structure entirely in favor of facilitating URL adjustments. While undoubtedly cumbersome and grossly inefficient, the reassurance of attaining successful outcomes merits contemplation amid looming hurdles stalling further progress.

Answer №1

After countless hours diving into documentation, scouring StackOverflow answers, browsing various websites, and dissecting AngularJS code morsels, I finally cracked the code.

Setting

$compileProvider.debugInfoEnabled(false)
detaches scopes from the document, but they are still accessible with some effort.

Referencing a helpful snippet provided by user Estus Flask in this StackOverflow answer, I realized that targeting an AngularJS-initialized element was crucial for success.

var scope;
angular.element(document.body).injector().invoke(function ($rootScope) {
  scope = $rootScope;
  console.log(scope);
});

Initially encountering issues due to an unconnected <body> within my app, redirecting attention to an AngularJS-initialized element like <primo-explore> proved to be the solution. Additionally, thanks to user sahbeewah's comment on another insightful answer discussing AngularJS scopes, a more concise syntax was presented.

To obtain the root scope, locate the main element of your app marked by the ng-app attribute or via a custom element such as <primo-explore>, then retrieve the root scope with:

let angRoot = document.getElementsByTagName("primo-explore")[0];
let rootScope = angular.element(angRoot).injector().get('$rootScope');

Depending on the scenario, methods like getElementById or getElementsByQuerySelector may be necessary instead of using getElementsByTagName.

With the root scope acquired, an insightful recursive function shared by user larspars facilitated discovering all defined scopes across the page.

// Function definition omitted for brevity
getScopes($rootScope)

Subsequently, leveraging a simple for loop allowed me to sift through over 600 scopes for the desired one:

// Code block iterating through scopes for target selection

Following this process, cleaning up redundant memory usage by setting scopes = undefined; and updating links ensured accurate display of information.

Through perseverance spanning nearly two work-weeks, victory was achieved in rectifying a single link - a triumph well-earned.

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

Using Rails to render a partial containing a form object

I need help with rendering a partial called 'colordata' after selecting a color from a dropdown list using Ajax. Unfortunately, I'm not seeing any changes on the main page and the form is undefined in the colordata partial. This is the sche ...

Unusual Glitch in Bootstrap 3 Dropdown Menu

I am currently developing a website using Bootstrap 3. I am encountering an issue with the navbar dropdown. When I click on the link, it changes to show "expand child menu" and "collapse child menu". To clarify, here is the image I am referring to: Initi ...

Dynamic data retrieval with the power of JavaScript and AJAX

When attempting to send data using AJAX in PHP, I encountered an issue with my jQuery click function on a button that sends data only when the quantity is greater than 1. The error arises because PHP does not recognize the variables 'name' and &a ...

New replacement for routerState.parent feature that has been deprecated in angular2

During my work with Angular 2 rc5, I encountered the following code snippet. this.router.routerState.parent(this.route).params.forEach((params: Params) => { url = params['url']; id = +params['id']; }); I had to resort to th ...

Tips for showing a single table with buttons on display

I am using R markdown and have included multiple tables with buttons, but when I open the file, all tables are displayed at once. How can I ensure only one table is shown upon opening the file? <script type="text/javascript"> function sh ...

Is there a way for me to confirm if a node module is compatible with bundling in Webpack and running in a web browser?

One of the advantages of using Webpack is its ability to bundle up node modules for use in an HTML page within a browser. However, not all node modules are compatible for this purpose. Certain modules, such as those utilizing the 'fs' module or n ...

Development is hindered due to Cors policy restricting access to the localhost webapp

Currently, I am working on developing a web application and an API simultaneously, but I'm facing some issues with CORS blocking. This concept is relatively new to me, and I'm eager to improve my understanding. Firstly, I have set up an Express ...

Example of AngularJS UI-Router Login Feature

Currently, I am delving into the realms of angularjs and bootstrap to develop a web application that will consist of two distinct sets of views - public and private. In the public view, all users will have access to it and there will be a specific top men ...

The issue of not being able to add data to the client is encountered in a local setup involving Socket.io, MSSQL

I have a large dataset that needs to be retrieved from a SQL server using Node.js and then broadcasted to clients in real-time using Socket.IO. I've been successful in fetching the data, but the UI on the client side isn't updating. Although I c ...

Is it possible to use AngularJS to show additional information between rows when a table row is clicked in HTML

I'm currently working on an html table where the <tbody> is generated using angular's ng-repeat. Take a look at my html: <tbody ng-repeat="car in carList | filter:tableFilter"> <tr> <td><a target="_blank" h ...

Tips for adjusting the margin of a print document in a printTask?

Is there a way to achieve a borderless print? Currently, my printed output has a border around it. I would like the image to start at the top left corner without any borders. I attempted to set a negative margin to the print-style box, but it resulted in ...

Express throwing module errors

I encountered an issue while attempting to expose a REST service in an electron app using expressJS. Following a tutorial, I added express and @types/express to the project. However, when trying to implement a "get" method and running the build with ng bui ...

What is the best way to move between websites or pages without having to reload the current page using a selector?

Have you ever wondered how to create a webpage where users can navigate to other websites or pages without seeing their address, simply by selecting from a drop-down menu? Take a look at this example. Another similar example can be found here. When visit ...

When executing JavaScript code, the file remains unchanged and does not alter the URL

I want my form to check a SQL database upon submission and execute a JavaScript file that captures the data into a constant. However, instead of running the JS script on the page as desired, it redirects to a new URL. Is there a way to ensure that the JS ...

Prevent MUI Autocomplete from closing when the option menu is opened with blur

Seeking assistance with modifying an autocomplete menu to include a dropdown for each item. Issue arises after trying to open the additional menu as it triggers an immediate closure of the autocomplete. For reference, attached is an image showcasing the i ...

JSON syntax error: "r" is not a valid token at the beginning position

Currently, I am in the process of developing a web server that is based on STM32 MCU. The workflow involves the browser sending a request to the MCU, which responds with a web HTML file. Users can then adjust parameters and use a form to submit them back t ...

The alignment of the JQuery Mobile tabs is off

As I work on developing a Cordova app, I've noticed that the tabs on my Android phone display in an unusual way. Here's what they look like: The image above was created in JSFiddle using JQuery 2.1.0 and JQM 1.4.2 selected with the following co ...

Error when navigating to a dynamic parameter path using Angular Router

I'm trying to redirect a user to a path with a unique UUID when they go to the root URL (localhost:4200). However, I encountered the following error: ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'document/4fdb ...

The JSON output from the gapi (Google Analytics) array in PHP is not displaying any values

I've been utilizing the gapi class within a CodeIgniter website. The implementation I'm using is based on this resource, which returns an array that functions perfectly. To pass this array to my JavaScript, I've been attempting the following ...

Verify Departure on External Links within Wordpress

Let me set the stage for you: We're dealing with a bank website here. So, whenever a user wants to click on an external link (could be to a Facebook page or a partner website), we need to have a notification box pop up saying "You are about to lea ...