Implementing custom CSS styles to a component in real-time with ng-style

When I use an angularjs component to create stylized pictures, the style is not applied correctly on the first visit to a page (refreshing the page shows the correct style). The CSS that should be applied is generated dynamically based on the height and width properties of the image being styled.

I am seeking advice on why the CSS works upon reload but not during the initial load, as well as how to resolve this issue so that the CSS is properly applied the very first time the page is loaded. Thank you in advance!

Here's my HTML code for creating a stylized picture:

<stylized-picture image-source="someImage.jpg"></stylized-picture>

The implementation of the stylizedPicture component:

.component('stylizedPicture', {
    templateUrl: 'src/components/stylized-picture.template.html',
    bindings: {
      imageSource: '@imageSource',
    },
    controller: 'StylizedPictureController as stylizedPictureController'
});

The content of stylized-picture.template.html:

<div ng-style="stylizedPictureController.outerCSS">
    <div ng-style="stylizedPictureController.innerCSS"></div>
       <div ng-style="stylizedPictureController.imgDivCSS">
           <img ng-src="{{stylizedPictureController.imageSource}}">
       </div>
    </div>
</div>

About the stylizedPictureController: The CSS adjustments are dependent on the dimensions of the image.

.controller('StylizedPictureController', StylizedPictureController);

StylizedPictureController.$inject = ['$scope'];
function StylizedPictureController($scope) {
    var ctrl = this;

    ctrl.$onChanges = function() {
      var img = new Image();
      img.addEventListener("load", function() {
        ctrl.imgWidth = img.naturalWidth;
        ctrl.imgHeight = img.naturalHeight;

        // Placeholder logic for styling image based on its dimensions
        var paddingBottom = 100;
        ctrl.paddingBottom = paddingBottom;
        ctrl.outerCSS = {"padding-bottom: " + paddingBottom + "%"};
        ctrl.innerCSS = {"padding-bottom: " + paddingBottom + "%"};
        ctrl.imgDivCSS = {"padding-bottom: " + paddingBottom + "%"};
      });
      img.src = ctrl.imageSource;
    };
};

I have experimented with using image.onLoad() instead of ctrl.$onChanges or the img event listener, but encountered similar outcomes. Additionally, attempts to set ng-style inline like

ng-style="{'padding-bottom': stylizedPictureController.paddingBottom}"
did not yield any differences.

Answer №1

After encountering a problem, I managed to find a solution which I wanted to share here in case anyone else runs into the same issue.

The key was to add the following code snippet:

$scope.$apply()

at the end of the image load EventListener. This should be done after the CSS has been generated and stored on the controller. By doing this, the issue was resolved. It seems that the problem arose because the image load occurred outside of the angularjs scope. As a result, when it finished loading, angular did not detect any changes and thus did not update the ng-style binding. Utilizing $scope.$apply() forces the update of bindings, resolving the ng-style display issue.

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

Encountering issues with the phaser framework while setting up a server on xampp, faced with errors in javascript and html

Recently, I've been working on a game using Phaser and encountered some issues while trying to run the code in XAMPP. The game's base is located at htdocs/itw/test.html, with the necessary pngs and json file stored in htdocs/itw/assets/. The pngs ...

What's causing nested promises to fail in my code?

Despite never having attempted nested promises before, I decided to give it a try based on what I've read and learned online. However, when implementing nested promises in my code, things didn't go as expected: APIService.getData(Config + header ...

What is causing my fetch response to not be passed through my dispatch function?

I'm currently utilizing a node server to act as the middleman between firebase and my react native app. Could someone kindly point out what might be going awry in my fetch method below? export const fetchPostsByNewest = () => { return (dispatch ...

The directive in an Angular app is not loaded due to lazy loading

Seeking assistance with lazy loading a directive in my Angular application, I am using ui.router and oc.lazyLoad. Below is the code snippet: menu : <ul> <li><a ui-sref="home">Home</a></li> <li><a ui-sre ...

In both Chrome and Edge, the default value for the <select> tag is successfully set, however, this functionality is not working in

I have defined two values in the created method, 2018 and My Name, and assigned them to separate data properties. These data properties are then passed as v-bind to a component. The issue I am facing is that in Chrome and Edge, both values are set as defa ...

Issue with Angular binding not updating after being assigned in promise.then() function

Within my angular application, I have a $scope variable labeled as user which contains a name property. Whenever I click on a link to set this user variable to "test": <a href="#" ng-click="setUser()">Set User</a> Using the following functio ...

What could be the reason that ngModel is failing to execute $setViewValue(...) when called

I am developing a directive that requires an isolated scope, but I also need to bind it to the parent scope using ngModel. However, I am facing an issue where the value of the parent's scope is not being updated. Below is the markup: <form name= ...

Error encountered in Angular: FormBuilder provider not found

I am currently utilizing Angular 9. An error that I am encountering is as follows: No provider for FormBuilder This issue has been documented in numerous instances, with the common solution being to include the FormsModule in the app.module.ts file. F ...

Issue: Using the useParams() hook triggers a TypeError, stating that useContext(...) is undefined

Having trouble with the useParams() react hook to fetch a parameter, and encountering this error: Error: useContext(...) is undefined The hooks file throws this error on line 40: /modules/hooks.js:40 39 | > 40 | const match = useContext(Context) ...

Leveraging TipTap.dev for building a joint editing platform -

I have integrated the collaboration feature from tiptap.dev into my NextJS application. Initially, I used their CLI command for the Hocuspocus server which worked well on port 1234 locally and synchronized text editing across browsers seamlessly. However, ...

Point the API endpoint to a different file

Is there a method to proxy a specific binary file, such as redirecting a PDF file to another PDF file using something like app.use('/proxy', proxy('/desiredPath'))? I have tried this approach, but it does not seem to work for the parti ...

Angular8: Stay Updated with Real-Time Data Refreshment

I've implemented code in my app.component to retrieve all users. I'm facing an issue where if I have two windows open and perform any CRUD actions, the second window displays outdated data. To address this, I am attempting to refresh the page ev ...

What are the best methods for implementing runtime type checking in JavaScript?

Utilizing either TypeScript or Facebook's Flow (type), I am empowered to statically assign types to variables like this: function add (x: integer, y: integer) { ... } Both TypeScript and Flow are able to identify and prevent incorrect invocations su ...

The JavaScript code is producing a numerical output instead of the intended array

I am facing an issue with my program that is designed to eliminate items from a list of arguments. function destroyer(arr) { var args = [].slice.call(arr); var data = args.shift(); for(var i = 0; i < args.length; i++){ var j = 0; while(j ...

It seems like there is an issue with the res.render function as it is

My goal is to capture an input from my main website. Once the input is submitted, the page should automatically redirect to /view. Despite successfully triggering the redirection with console.log(), the res.render function does not seem to be working as ex ...

Select elements in jQuery using both a specific selector and a negative selector

I am currently working with a JQuery function that highlights a specific word and scrolls to it: $('article.node--article p, .video-title').highlightWordAndScroll({ words : search_word, tag : '<span class="found_key ...

Exploring the depths of nested collections in Angular 12

As I work on my very first Angular/Firestore app, I find myself grappling with understanding how to retrieve data from nested collections. The Firestore database path that I need to access is as follows: /Customer(CollectionName)/cl0Apvalb6c0w9hltQ8AOTF4go ...

Tips for converting JSON object values to a string using JavaScript

Consider the following JSON object: { "id": 1, "name": "Name", "surname": "Surname", "number": "111111111" } Is there a way to transform this JSON object into a string that formats it as follows using JavaScript? Name Surname 111111111 ...

When attempting to deserialize a 2D array in JSON, it unexpectedly returns as a string instead of

I am trying to figure out how to deserialize the JSON string provided below into a two-dimensional array object using JavaScript. Whenever I attempt to use JSON.parse or eval, it ends up getting converted into a string format. Currently, I am utilizing D ...

A different component experiences an issue where Angular Promise is returning undefined

This is the carComponent.ts file containing the following method: async Download() { try { const settings = { kit: true, tyres: true, serviced: false, }; const [kits, tyres] = await Promise.all([ this.c ...