Shopping Directive Coverage Discrepancy

In my application, there is a shop item directive that includes a price attribute. When a user interacts with the directive, the total cost (a variable stored in the main controller) should be updated by the price of the item that was clicked.

Unfortunately, I am currently facing difficulties transferring the price attribute from the shop item directive to the main controller. Any suggestions or assistance would be greatly appreciated.

HTML:

<div ng-app="Shop" ng-controller="MainCtrl">
  <p>The total cost is {{ total }}.</p>
  <shop-item price="100"></shop-item>
</div>

JavaScript:

var app = angular.module('Shop', []);

app.controller('MainCtrl', ['$scope',
  function($scope) {
    $scope.total = 0;
  }
]);

app.directive('shopItem', function() {
  return {
    restrict: 'E',
    template: '<div class="shop-item">Shop Item</div>',
    scope: {
      price: '@'
    },
    link: function(scope, element, attrs) {
      element.on('click', function() {
        // Need help updating the main controller's total based on the 'price' attribute of this directive
      });
    }
  };
});

Answer №1

There are many approaches to solving this issue. One simple way, like the one you mentioned, is to use function binding to handle the click event or implement 2-way binding.

Using 2-way binding

<div ng-app="Shop" ng-controller="MainCtrl">
  <shop-item price="100" total="total"></shop-item>
</div>

Instead of manually binding the event handler in the directive, use angular's events, for example, ng-click

app.directive('shopItem', function() {
  return {
    restrict: 'E',
    /*register an ng-click*/
    template: '<div class="shop-item" ng-click="addItem()">Shop Item</div>',
    scope: {
      price: '@',
      total: '=' //<-- 2 way binding
    },
    link: function(scope, element, attrs) {
       scope.addItem = function(){
          //increment the price
          scope.total = (scope.total || 0) + +scope.price;
       }
    }
  };
});

Check Plnkr for Demo

Using Function Binding

Another approach is to use function binding where the controller handles the price calculation instead of the directive. This separation of concerns can make the code easier to manage and understand. For example:

<shop-item price="100" total="total" on-add-cart="addToCart(price)">  </shop-item>

In the controller:

$scope.addToCart = function(price){
   $scope.total += price;
}

In the directive (adding a discount of 5% as an example):

app.directive('shopItem', function() {
  return {
    restrict: 'E',
    /*register an ng-click*/
    template: '<div class="shop-item" ng-click="onAddCart({price: (+price)*.95})">Shop Item</div>',
    scope: {
      price: '@',
      onAddCart: '&' //<-- 2 way binding
    },
    link: function(scope, element, attrs) {
       scope.addItem = function(){
          //increment the price
          scope.total = (scope.total || 0) + +scope.price;
       }
    }
  };
});

Check Plnkr for Demo

Using Event Bus

Alternatively, you can utilize the angular event bus by utilizing $emit or $broadcast with $on. The choice between $emit/$broadcast depends on the DOM element hierarchy. An example:

<shop-item price="100" total="total">  </shop-item>

In the directive:

 return {
    restrict: 'E',
    /*register an ng-click*/
    template: '<div class="shop-item" ng-click="onAddCart()">Shop Item</div>',
    scope: {
      price: '@'
    },
    link: function(scope, element, attrs) {
      scope.onAddCart = function(){
        scope.$emit("ITEM_ADDED", +scope.price); //emit an event with price
      }
    }
  };

In the controller:

$scope.$on('ITEM_ADDED', function(e, price){
   $scope.total += price;
});

Check Plnkr for Demo

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

Is there a way to detect when a user is interacting with a form item using Vue and Buefy?

I'm interested in activating an event when a user focuses on a form element created using Vue / Buefy. As a newcomer to this, I would appreciate any guidance on how to accomplish this triggering action. ...

When using State.go(), the url in the address bar will update, but the HTML view will not be refreshed

Encountering an issue while working on Ionic with AngularJS, specifically with the routing system when attempting to create a login page. In the controller section of the code, I am trying to navigate to a welcome page called 'dash' using state.g ...

Sending data using jQuery to a web API

One thing on my mind: 1. Is it necessary for the names to match when transmitting data from client to my webapi controller? In case my model is structured like this: public class Donation { public string DonorType { get; set; } //etc } But the f ...

Enhance your TypeScript arrays using custom object equality functions

I am looking to utilize array functions such as contains and unique, but I want them to compare equality using my custom equals function. For instance: let arr = [{id:1,..//some more},{id:2,..//some more},{id:3,..//some more}] I need the following code ...

Issue with data retrieval from Firebase snapshot reference

While working with Firebase, I encountered an issue related to setting and getting priorities of items in a list of people. Surprisingly, the functionality seems to work fine in one function but throws an error in another. When trying to get the priority ...

Obtaining the text content of a <div> element when clicked using Selenium

I am trying to extract the email address from the code snippet below, but I am unsure of how to do it. Any assistance would be greatly appreciated! <div class="taLnk hvrIE6 fl" onclick="ta.trackEventOnPage('Listing', 'Email', 774169 ...

Diving into Redux brings up the question of whether to use a generic reducer or a

When working with Redux, what is the preferred approach: Creating entity-specific reducers or utilizing a generic reducer based on strict action keying conventions? The former can result in more boilerplate code but offers loose coupling and greater flexib ...

When Vue detects a change in declared parameters from an empty string, it automatically sends a

Within my application, I am making a request to the backend app and receiving a response with an ID such as { 'id': '12345'}. This ID is then saved as loadId within the data object: export default { name: 'SyncProducts', d ...

Issue: React child must be a valid object - Runtime Error Detected

As I delve into the world of React, NextJs, and TypeScript, I stumbled upon a tutorial on creating a navbar inspired by the 'Strip' style menu. It has been quite a learning journey for me as a newbie in these technologies. After seeking help for ...

Tips for removing a previous file from an 'input type' in HTML5 FileReader

Here is a file input with an associated function: <img id="uploadPreview"> <div id="changeImage">Change</div> <div id="customImage"> <input type="file" id="myfile" multiple style="display:none" onchange="PreviewImage();" / ...

What is the best way to modify an image in a column when I hover over a table row that was dynamically inserted using a button function?

Is there a way to dynamically change an image in a column when hovering over a table row that was added through a button function? Here is the current code that I am using, but it does not seem to work as intended when I hover over the row. This function ...

Ways to hide notifications by setting a timer while keeping the delete option visible

Presently, this is the code I am working with using Javascript and Vue.js. I have an array called Messages.length that contains messages. When the x button is clicked, it triggers the "clearMessages(item)" function on the server side. However, I also aim ...

Data in the array is only updated upon refreshing the webpage

Why is the array empty when I navigate to a new route (/category/name-of-category) that renders my Category component, but it gets data when I refresh the page? What am I missing here? To better explain, I have created a video. Video showcasing the issue: ...

Looking to distinguish selected options in a multiple select in AngularJS by making them bold?

When working with Angular, I have a multiple select drop down with options such as Select fruits, Apple, Orange, Banana. How can I make the selected options, like Banana and Apple, appear in bold and change background colors? ...

Navigate to a specific section in an Accordion with the help of jQuery

I currently have 2 pages: page1.html, which contains a series of links, and page2.html, where an Accordion is located. The Query: I'm wondering if it's feasible to link directly to a specific section within the Accordion. For instance, if I want ...

Why is this loop in jQuery executing twice?

$(document).bind("ready", function(){ // Looping through each "construct" tag $('construct').each( alert('running'); function () { // Extracting data var jC2_events = $(this).html().spl ...

Using HTML and JavaScript to create a link that appears as a URL but actually directs to a JavaScript function

I am working on an HTML page and I am trying to create a link that appears to go to 'example.html' but actually goes to 'javascript:ajaxLoad(example.html);'. Here is what I have tried: <a href="example" onclick="javascipt:ajaxLoad( ...

The Material-UI selector isn't functioning properly for me

I recently tried to incorporate a material-ui selector example into my project by referring to the code fragment obtained from an example on Github. import React from "react"; import {withStyles} from "material-ui/styles"; import Select from "material-ui/ ...

Exploring AngularJS: Understanding the Resource Factory and Callback Functions

As a newcomer to Angular, I'm facing some challenges when it comes to managing data with $resource in a factory. I am transitioning from using $http requests to $resources in my factory. Initially, my code looked like this (simplified version): .fac ...

The submit button is not reading the JavaScript file for validation and instead goes directly to my PHP file

**Hello, I'm new to Stack Overflow. My submit button is not reading the JavaScript file I created; instead, it goes straight to the PHP file without validating the input fields first in the JavaScript file. I've been stuck here for hours and can& ...