A guide on creating an Angular.js directive for extracting data from the DOM

As a newcomer to Angular.js, I find myself in need of assistance with a minor issue. Sadly, the CMS that I am working within lacks a service and does not output JSON. This leaves me with no other choice but to extract my data from the DOM. While this may not be the optimal solution, it is the reality of my current situation.

Within the page, there exists a hidden div styled with CSS and containing an unordered list with the class of .people-data. In essence, this hidden element serves as my makeshift service :)

I suspect that I should encapsulate my jQuery logic for scraping data from the DOM within a 'directive,' but I am uncertain how to proceed. It feels inappropriate to have this jQuery code residing directly within the controller.

Perhaps, I might not even require jQuery to access this data... Could Angular perform such tasks?

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

angularApp.controller('PeopleCtrl', ['$scope', function PeopleCtrl($scope) {

$scope.people = [];

    // prefer not to include this within controller.. extracting data from DOM
    // perhaps a directive?? where and how should it be implemented?
    $('.people-data li').each(function(){
      $scope.people.push({ 
          name: $(this).find('.name').text(), 
          email: $(this).find('.email').text() 
      });
    });

} ]);

For reference, you can view the Plunk here: http://plnkr.co/edit/kUqL9f?p=info

Answer №1

I created a fresh Plunk with a directive here: http://plnkr.co/edit/Q9FLIyWSzfm77SbvyBys?p=info

Essentially, you simply need to include:

angularApp.directive('domScraper', function() {
  return {
    restrict: "A",
    link: function(scope, element, attr) {
      scope.people = [];
      $('.people-data li').each(function() {
        scope.people.push({
          name: $(this).find('.name').text(),
          email: $(this).find('.email').text()
        });
      });
    }
  }
});

After that, just add the attribute dom-scraper to the element where your controller is set.

<div ng-app="angularApp" ng-controller="PeopleCtrl" dom-scraper>

I included a console.log in your controller to demonstrate that the directive and the controller share the same scope, as I am unsure about your data handling intentions.

In your index.html, I rearranged jquery and angular. Angular utilizes a lightweight version of jQuery, unless you are importing a jQuery library prior to the angular library. As you are importing jQuery, it is advisable to place it before. You can read about it here: https://groups.google.com/forum/#!topic/angular/6A3Skwm59Z4

Trust this information proves useful.

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

Stopping unauthorized users from manipulating REST URLs

I am currently exploring methods to prevent an exploit where a user manipulates the URL, specifically in a GET request scenario. The following code represents a route on my Express router that processes incoming requests for a certain collection "A" and re ...

Using jQuery validation to verify that a minimum of one radio button holds a true value

I have a form with two questions. The first question asks if the product value exceeds a certain fixed amount, and the second question asks if the product value is below that fixed amount. Upon submitting the form, validation should ensure that at least on ...

The default theme has not been specified in Tailwind CSS

During my recent project, I utilized React, Next.js in combination with Tailwind CSS. In this project, I delved into styling customization by implementing react-slick for a specialized slider. To achieve the desired aesthetic, I made modifications to the r ...

What are the steps to resolve the issue of "npm ERR! EEXIST: file already exists, rename" occurring with non-existent files?

Welcome to my first question post. (Please be kind if I make mistakes.) I am using node version 5.6.0. For an assignment, I downloaded a JS web app but am encountering an error that is preventing me from working on it: S:\PersonalCloud\jennyly ...

What is the method for transferring HTML content to a Thymeleaf fragment without the use of the layout dialect?

Is it possible to use Thymeleaf out of the box without the need for the layout dialect? Currently, you can define a fragment like this: <div th:fragment="my-custom-accordeon"> <th:block th:insert="~{::h1}></th:block> ...

Collect user input from an array of checkboxes

After spending hours attempting to retrieve data from an array of checkboxes with the same name, I am still facing difficulties. <input type="checkbox" name="node"/> var selectedValues = []; $(document.getElementsByName("node")).each( ...

Using Backbone for the front end and Node.js for the backend, this website combines powerful technologies

Currently, I am in the process of developing a new website that will function as a single-page application featuring dialog/modal windows. My intention is to utilize Backbone for the frontend and establish communication with the backend through ajax/webs ...

Best practice for integrating configuration settings into a Redux application

One essential step before launching my application is to read the config.json file. This file contains the URLs to my backend services, which will be utilized in my Redux action creators. I have contemplated two different approaches: Fetching the JSON a ...

Which would be more advantageous: using a single setter method or multiple setter methods for objects that have a set number of fields?

As I ponder over designing a class with a member variable of type object containing a fixed number of fields, the question arises: should I opt for a single setter function or multiple setters to modify these fields? To illustrate this dilemma clearly, I ...

Angular JS provides a useful input directive called ng-pattern that allows developers to apply regular

Seeking help to validate an IP Address in a text box using ng-pattern. CODE: <input name="machinestodiscover" type="text" ng-model="machinestodiscover" ng-minlength="7" ng-maxlength="15" ng-pattern="/\b([0-9]{1,3})[.]([0-9]{1,3})[.]([0-9]{1,3})[. ...

How can I apply a style to text when I double click on it?

Rephrased: There is an input field on my webpage: <input type="text" id="some_id" /> I type some text into the input field: Here is my text! If I double click on the word "my", am I able to: Retrieve this value? Yes, the answer is provided belo ...

Having trouble getting my JS/CSS code to work for a single image music play/pause button. Any suggestions on how to fix it?

I'm currently working on a project and trying to incorporate a music button into the navigation bar. The goal is for the song to play when clicked, and then pause when clicked again. However, I've encountered some issues with getting it to functi ...

Automatic session destruction in Laravel 5.1 when using AngularJS is a seamless process

Session in laravel 5.1 automatically ending My server side is Laravel and client side uses AngularJS. Even though I'm storing session data in root scope and window Storage for the front end, my application sometimes experiences random session destru ...

Challenges encountered when retrieving parameters from union types in TypeScript

Why can't I access attributes in union types like this? export interface ICondition { field: string operator: string value: string } export interface IConditionGroup { conditions: ICondition[] group_operator: string } function foo(item: I ...

Positioning Images with CSS Backgrounds

I am looking to create a fluid background that stretches widthwise, while adjusting its height based on the content. If the content is smaller, I want the background to be truncated. However, if there is a lot of information, I would like the background to ...

Polymer element created specifically for this project can be seen in the DOM, yet it does not display any content within the

Snippet: <link rel="import" href="../../../../bower_components/polymer/polymer.html"> <link rel="import" href="../../../../bower_components/app-layout/app-drawer-layout/app-drawer-layout.html"> <dom-module id="app-index"> <templa ...

Can you explain the steps to implement the defer render functionality in my datatable?

I have a DataTable that I want to apply deferred rendering on, but I am encountering an issue. My controller method returns an array of JSON objects. Please refer to the code snippet below. **Setting up the DataTable ** This code is executed when the pag ...

Reacting like sticky bottoms and tops

I'm working on a react/tailwind project that involves a component I want to be fixed at both the top and bottom of the screen. In simpler terms, there's an element that I need to always stay visible even when the user scrolls up or down the page ...

Function in Node.js that accepts an integer without a sign and outputs an incorrect count of '1' bits

When using this NodeJS function with input in signed 2's complement format, it is returning an incorrect number of '1' bits. The intended output should be 31, but the function is currently only returning 1. var hammingWeight = function(n) ...

Optimal approach for choosing/emphasizing text (within a text input field) in Vue (utilizing computed properties for input value and selection range)

Our current setup involves a text input field with its value stored in Vuex, passed as props, and accessed through computed properties. Within the same Vuex store, we also have a selection range (an array of two numbers) that allows text in the input to be ...