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

Achieving functionality with a fixed header

I am struggling with the scroll functionality and smooth transition in my code for a sticky header. The scroll doesn't work smoothly, especially when the fixed header is activated. The #top-nav-wrapper barely scrolls as expected: <script> $(doc ...

Navigating through the Express.js routes incorrectly

I currently have 3 different express.js routes set up: app.get('/packages/:name', (req, res) => {...}); app.get('/packages/search/', (req, res) => {...}); app.get('/packages/search/:name', (req, res) => {...}); At t ...

Close specific child python processes as needed, triggered by a jQuery event

Having trouble managing child processes independently without affecting the main parent process in a web client using jQuery? Look no further. Here's my scenario: I've got a Flask server hosting a basic webpage with a button. Clicking the button ...

How come the array's length is not appearing on the browser screen?

Code: initialize: function() { this.todos = [ {id: 100, text: 'Rich'}, {id: 200, text: 'Dave'} ]; }, activeTodos: function() { this.todos = this.todos.length(function() { return this.todos; }); ...

Event fails to trigger when attached to different elements

Currently, I have an onchange event linked to the input text box and an onclick event attached to a text link. Interestingly, when I click on the link after editing the textbox, the click event does not trigger - instead, the change event is fired. If you ...

Assigning an interface to a useFetch object in Vuejs 3 and Nuxtjs 3: A step-by-step guide

Need assistance with assigning an interface to a useFetch object in Vuejs 3 Interface export interface ProdutoInterface { codigo: number nome: string } Componente const { data: produto, error } = await useFetch(config.API_BASE_URL+`/produto`) I&apos ...

Can I link the accordion title to a different webpage?

Is it possible to turn the title of an accordion into a button without it looking like a button? Here is an image of the accordion title and some accompanying data. I want to be able to click on the text in the title to navigate to another page. I am worki ...

JQuery does not operate on content that is fetched through ajax requests

I've been struggling with this issue for quite some time now and I just can't seem to figure out what I'm doing wrong. (I suspect it's related to the ajax response) I attempted to upload an image to the server using the uploadifive plu ...

How come I keep running into the "is not a function" issue when trying to use the generateRequest function with Polymer's iron-ajax

Oops, it seems like there was an error: Uncaught TypeError: this.$.ajax.generateRequest is not a function. The issue seems to be in assets-ajax.html at line 23. <dom-module id="assets-pull"> <style> </style> <template> <but ...

Live Search: Find Your Answers with Ajax

I've come across this issue multiple times, but haven't found a solution that fits my specific requirements. I've encountered several URLs with links like example.com/ajax/search?query=Thing I'm currently working on a header and using ...

Error: Attempting to access the 'getCroppedCanvas' property of an undefined value in VueJs

I've been exploring the vue-cropperjs library, but every time I execute the code, I encounter error messages: Uncaught TypeError: Cannot read property 'getCroppedCanvas' of undefined Uncaught TypeError: Cannot read property 'replace&ap ...

Is there a way to align my two tables next to each other using CSS?

.page { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 20px; } .items { float: left; } .secondItem { vertical-align: text-top; float: right; } .page-header table, th, td { border: 1px solid; display: block; background-color: ...

Tips for muting console.log output from a third-party iframe

As I work on developing a web application using NEXT.js, I am encountering an issue with a third party iframe that is generating numerous console logs. I am seeking a way to silence these outputs for the iframe. The code in question simply includes an < ...

Passport.js: Navigating Users in the Right

I've been working on integrating passport.js, passport-google-oauth, and nodjes to retrieve a user's profile locally. However, I'm facing an issue with the redirect after logging in. Although the information is successfully loaded (I can acc ...

Obtaining the jqXHR object from a script request loaded within the <head> tag using the <script> tag

Is it possible to retrieve the jqXHR object when a script loaded from a script tag within the head tag? function loadScript(url){ const script = document.createElement("script"); script.src = url; // This line will load the script in the ...

Instructions for enabling the touch slider feature in the Igx carousel component with Angular 6 or higher

Looking to enable the touch slider for Igx carousel using angular 6+? I am trying to implement the igx carousel for image sliding with reference from a stackblitz demo (https://stackblitz.com/edit/github-j6q6ad?file=src%2Fapp%2Fcarousel%2Fcarousel.compone ...

Contrasting the Javascript onload event with plain script within an html page

Can you identify the distinction between these two code snippets: Sample 1: <script type="text/javascript> function myfunc () { alert('hi'); } window.onload = myfunc; </script> Sample 2: & ...

Sending data to a React Dialog component using the OnClick event

I am a beginner learning React.js and currently experimenting with passing parameters to a dialog box using onclick events. <IconButton className={classes.approvebutton} onClick={() => handleDialogClick("approve",1)}> <ThumbU ...

Position the caret after adding a new element in a content-editable div

I have a contenteditable div that contains various elements. My goal is to automatically create a new paragraph tag right after the element where the cursor is positioned when the user presses the enter key. Currently, I am able to insert the paragraph tag ...

Add a library to a server with npm installation

When needing to incorporate a library like Croppie, the installation process involves using npm or Bower: npm install croppie bower install croppie Given that I am working on a server, I'm uncertain where to install it. Should it be on the server it ...