Possible scope problem causing AngularJS image preview not showing up in ng-repeat loop

I came across this question and made some modifications. It works well when used outside of the ng-repeat.

However, I'm facing issues when trying to use it within my repeat loop; the image.src does not update. I believe this is more related to the scope rather than the preview function itself. The console log on line 13 in the Plunker shows a string image, which should actually be the object from the loop.

So, how can I achieve the preview image after selecting a file?

Link to Plunker.

HTML:

<div ng-repeat="image in data.CmsPageImages">
    <a href="" ng-click="removeImage($index)" class="pull-right">
        <i class="fa fa-times"></i>
    </a>
    <input
        image-callback="test1"
        type="file"
        wa-file-select
        ng-model="image.file">
    <input
        type="text"
        required
        placeholder="Caption and copyright"
        ng-model="image.caption">
    <img ng-if="image.src" ng-src="image.src" style="width: 120px; height: auto;" />
</div>

JS code:

angular.module('waFrontend', []);

angular.module('waFrontend').directive('waFileSelect', ['fileReader', function (fileReader) {
    return {
      require: '^ngModel',
      scope: {
        imageData: '='
      },
        link: function ($scope, el, attr) {
            el.bind('change', function(e) {
              var file = ((e.srcElement || e.target).files[0]);
          fileReader.readAsDataUrl(file, $scope).then(function (result) {
                attr.imageData.src = result;
            });
            })
        }
    }
}]);

angular.module('waFrontend').controller('SubmitNewsController', [
    '$scope', 'fileReader',
    function ($scope, fileReader) {

    $scope.data = {
        CmsPage: {
            title: ''
        },
        CmsPageImages: [
            {
                caption: '',
                file: null
            }
        ]
    };

    $scope.addImage = function() {
        $scope.data.CmsPageImages.push({
            caption: null,
            file: null
        });
    };

    $scope.removeImage = function(index) {
        $scope.data.CmsPageImages.splice(index, 1);
    };

    $scope.getFile = function(file, test) {
        $scope.progress = 0;
        $scope.file = file;
        fileReader.readAsDataUrl($scope.file, $scope).then(function (result) {
            $scope.imageSrc = result;
        });
    };

}]);

(function (module) {

    var fileReader = function ($q, $log) {

        var onLoad = function (reader, deferred, scope) {
            return function () {
                scope.$apply(function () {
                    deferred.resolve(reader.result);
                });
            };
        };

        var onError = function (reader, deferred, scope) {
            return function () {
                scope.$apply(function () {
                    deferred.reject(reader.result);
                });
            };
        };

        var onProgress = function (reader, scope) {
            return function (event) {
                scope.$broadcast("fileProgress",
                        {
                            total: event.total,
                            loaded: event.loaded
                        });
            };
        };

        var getReader = function (deferred, scope) {
            var reader = new FileReader();
            reader.onload = onLoad(reader, deferred, scope);
            reader.onerror = onError(reader, deferred, scope);
            reader.onprogress = onProgress(reader, scope);
            return reader;
        };

        var readAsDataURL = function (file, scope) {
            console.log(file);
            var deferred = $q.defer();

            var reader = getReader(deferred, scope);
            console.log(file);
            reader.readAsDataURL(file);

            return deferred.promise;
        };

        return {
            readAsDataUrl: readAsDataURL
        };
    };

    module.factory("fileReader", ["$q", "$log", fileReader]);

}(angular.module("waFrontend")));

Answer №1

When you use console.log(attr.imageData), only the attr string that you're inputting will be shown. To view the image object exactly, you should utilize <code>$scope.$eval(attr.imageData)
.

Additionally, don't forget to include the imageData parameter in your directive:

<input
    image-callback="test1"
    image-data="image"
    type="file"
    wa-file-select
    ng-model="image.file">

or remove it from the directive scope initialization to avoid potential errors.

attr.imageData.src = result; won't work as intended. Use $scope.imageData.src = result instead.

It appears that ng-model="image.file" is not necessary in your directive, and require: '^ngModel' can also be removed unless required for future needs.

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

In the event that the $state cannot be located, redirect to a different URL using Ui

Our platform is a unique combination of WordPress backend and AngularJS frontend, utilizing ui.router with html5 mode turned on and a base href="/" due to the stack sites being in the root of the site. We are currently facing an issue: 1) Previously, whe ...

Utilize React to process and submit payments through Stripe

I am currently working on integrating Stripe Elements with my React application. The JavaScript page below showcases the code I use to submit the payment form, which I have compiled from various sources online. Upon submitting the form, I receive a token; ...

Using Database Data in a Material UI Select Component

I'm having trouble populating a select component from Material UI with data retrieved from my database. Although I can display the data in the component, upon selecting an option it breaks and displays the error "categorias.map is not a function". Any ...

What is the process for importing a jquery plugin like turnjs into a React component?

After searching through countless posts on stackoverflow, it seems like there is no solution to my problem yet. So... I would like to integrate the following: into my react COMPONENT. -I attempted using the script tag in the html file, but react does no ...

Flick user media cards left or right to uncover the following one

I am currently working on creating a widget that will display user media objects in a horizontal layout using ng-repeat. The goal is to allow users to swipe left or right to reveal the next media card, similar to the image shown below. In the example, you ...

Tally of number series in an array

If my array looks like [0, 2, 4, 10, 10, 10, 10, 2, 5, 3, 2, 10, 10, 5, 7, 4, 10, 10, 10, 10] How do I determine the number of times a sequence of 10's occurs with at least 3 repetitions. In this example, the output would be 2 because there are 2 s ...

A guide to generating numerous SVG paths using a JavaScript function

Creating strokes with similar length but different angles of rotations can be achieved efficiently using JavaScript instead of writing redundant lines of code. The following code snippet demonstrates one way to achieve this: function stroke(rot) { var d ...

Tips on effortlessly updating the URL of your website

Despite seeing the question asked multiple times, I still find myself struggling to understand how to modify a URL or create a new HTML page that seamlessly integrates into a website without redirecting users. I am curious about achieving the functionalit ...

The concept of nesting templates in Angular

I'm encountering an issue with my directive that has an item template recursively referencing itself, but it's not rendering out children beyond the first level. Despite checking various examples, the only difference I can spot is that my items a ...

I want to display a background color using this ng-template

enter image description hereMy code includes an ng-template that uses ngFor to generate internal HTML tags without the ability to add CSS properties. <ng-template *ngFor="let c of colors" contextMenuItem let-item (execute)="change_task_color($event.ite ...

Is it possible for links to remain clickable even if they pass underneath a div

I have implemented a shadow using a div element to cover some content beneath it. However, I am facing an issue where the div that is under the shadow cannot be interacted with. Is there any solution to this problem? Thank you ...

properties remain unchanged even after the state has been updated

Within my application, I have a component called Player. This component generates a div element containing an image and has properties named x and y. The values of these properties determine the left and top position of the div rendered by Player. Outside ...

Angular 14 is experiencing issues with NgRx Store failing to properly recognize the payload

The issue lies in TypeScript not recognizing action.payload.index as a valid property. I am unsure how to resolve this problem and make the 'index' visible in my project. shopping-list.actions.ts import {Action} from "@ngrx/store"; im ...

ACE editor error: Attempted to access the 'getValue' property of an undefined object

In the process of developing an Angular markdown editor, I have integrated the ACE editor as a code editor. The npm package for ACE editor can be found here. You can access a codesandbox version of the project here. My current challenge involves retrievi ...

The tooltip content is a little too narrow

I have successfully implemented QTip2 to display a tooltip: The content of the tooltip is generated in the following method: public string GetHours() { DateTime d = Convert.ToDateTime(Request.Form["date"]); Bump b = new Bump(); ...

Using regular expressions to eliminate text located outside of the tags within a string

Presented is a string consisting of an XML string below: var xmlString = "<str>rvrv</str>rvrv<q1>vrvv</q1>vrvrv<q2>rtvrvr</q2>"; I am seeking assistance on how to eliminate text that lies outside the tags (text no ...

An elementary React project facing compilation issues

I'm currently exploring react hooks, but I encountered an error with the useReducer hook. The console displays the following error message: "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happe ...

execute a function from a separate file in a node.js environment

How can I call the /getJobs endpoint inside the job.js node script? I'm currently using this approach, but I'm receiving an error stating "$ is not defined". job.js var jobSchedule = function (time, jobId) { var params = { "id": jo ...

In my development environment, the page does not have scroll functionality, but in the production environment, it is scrollable

Whenever I open a table or any other element with overflowing content, I encounter an issue with the scrolling bar. Even though the CSS includes overflow-y: scroll;, the scroll bar on the right remains in gray and does not allow me to scroll down when the ...

Issue with React / Express failing to route links accurately

Currently, my React project is functioning well except for Express. I have been struggling to find comprehensive tutorials on implementing correct routing with Express in a MERN stack application. I have come across some Stack Overflow posts, but none of ...