The art of revealing and concealing code blocks in AngularJS

I am currently working on a task in my AngularJS project. The requirement is that when both point directives within the md-autocomplete code are filled, the results directive should be displayed immediately without the need for any button. Additionally, if I press the cross icon to clear one of the autocomplete fields, the block should hide automatically.

Unfortunately, my code is not functioning as expected

Please note and look for any errors in the browser console section.

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

app.controller('mainCtrl', function($scope){
    $scope.interim = false;

    $scope.go = function(){
        $scope.interim = true;
    };
});

app.directive('point', function(){
    return {
        restrict: 'AE',
        template: '<div layout layout-sm="column">' +
                    '<md-autocomplete ng-disabled="isDisabled" md-no-cache="noCache" md-selected-item="selectedItem" md-search-text-change="searchTextChange(searchText)" md-search-text="searchText" md-selected-item-change="selectedItemChange(item)" md-items="item in querySearch(searchText)" md-item-text="item.display" md-min-length="0" placeholder="{{place}}">' +
                        '<md-item-template>' +
                             '<span md-highlight-text="searchText" md-highlight-flags="^i">{{item.display}}</span>' +
                        '</md-item-template>' +
                    '</md-autocomplete>' +
                '</div>',
        controller: PointCtrl,
        scope: {
            place: '@',
            go: '&'
        }
    }
});

function PointCtrl($scope, $rootScope, $timeout, $q, $log) {

    $scope.simulateQuery = false;
    $scope.isDisabled = false;

    $scope.cities = loadAll();
    $scope.querySearch = querySearch;
    $scope.selectedItemChange = selectedItemChange;


    function loadAll() {
        var allCities = 'London, Manchester, Liverpool, Paris, Lion, Prague, New York, Dallas';

        return allCities.split(/, +/g).map(function (city) {
            return {
                value: city.toLowerCase(),
                display: city
            };
        });
    }

    function querySearch(query) {
        var results = query ? $scope.cities.filter(createFilterFor(query)) : $scope.cities,
            deferred;
        if ($scope.simulateQuery) {
            deferred = $q.defer();
            $timeout(function () {
                deferred.resolve(results);
            }, Math.random() * 1000, false);
            return deferred.promise;
        } else {
            return results;
        }
    }

    function createFilterFor(query) {
        var lowercaseQuery = angular.lowercase(query);

        return function filterFn(city) {
            return (city.value.indexOf(lowercaseQuery) === 0);
        };
    }

    function selectedItemChange(item) {
        $log.log('value: ' + item.display);
        $scope.chosenPoint = item.display;

        $scope.$watch('chosenPoint', function (newVal, oldVal) {
            if (newVal !== '') { //if autocomplete field is completed
                $scope.go(); //show block with results directive
            } else {
                //$scope.hideBlock(); //if not or cleared - hide block
            }
        });
    }
}

app.directive('results', function() {
    return {
        restrict: 'AE',
        template: '<div style="width: 400px; height: 200px; background-color: red; font-size: 30px; text-align: center" ng-show="interim">I need to show this block when autocomplete fields are filled and hide it when both or, at least, one of the fields are cleared, pressing a cross</div>'
    }
});
<html ng-app="app">
<head>
    <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.0-rc7/angular-material.min.css">
    <style>
        .resultsBlock {
            width: 400px;
            height: 400px;
            font-size: 14px;
        }

        h3 {
            margin: 20px 0;
        }

        md-autocomplete button{
            position: relative;
            left: 100px;
            line-height: 20px;
        }

        md-autocomplete input:not(.md-input) {
            font-size: 14px;
            width: 40%;
        }
    </style>
</head>
<body ng-controller="mainCtrl">
    <div class="resultsBlock" layout="column">
            <point place="point_1"></point>
            <h3>Block of text will be shown when both autocomplete fields will be completed</h3>
            <results></results>
            <point place="point_2" go="go()"></point>
    </div>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular-animate.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular-aria.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angular_material/0.9.4/angular-material.min.js"></script>
    <script src="main.js"></script>
</body>
</html>

Answer №1

When you interact with the point directive and click on x to delete the selection, the selectionItemChange function is called with an undefined item parameter, leading to an error in the console.

To resolve this issue, modify your function to handle this specific condition.

Update to your point directive:

function selectedItemChange(item) {

    //add event emitter
    $scope.$emit("pointChange", item);

    if (item) {
        $scope.chosenPoint = item.display;
    } else {
        //set to empty string if 'item' parameter is undefined
        $scope.chosenPoint = '';
    }

    if ( $scope.chosenPoint !== '') { 
        //if autocomplete field is completed
        $scope.go();
    }
}

Additionally, take note of the new event emitter added. Listen for this event in your main controller to utilize it for clearing the block when needed.

Update to your main controller:

app.controller('mainCtrl', function($scope){
    $scope.interim = false;

    $scope.$on("pointChange", function (e,item) {
        if (!item) {
          console.log("Clearing block");
          $scope.interim = false;
        }
    });

    $scope.go = function(){
        $scope.interim = true;
    };
});

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

Modify text using JQuery when the span is clicked

Currently, I am attempting to retrieve a value from the database: SenderDriver->total_trips. Everything seems fine, but I have a specific id that needs to be placed within onClick(), which then sets the value of the database variable: SenderDriver-> ...

Leveraging NestJs Libraries within Your Nx Monorepo Main Application

I am currently part of a collaborative Nx monorepo workspace. The setup of the workspace looks something like this: https://i.stack.imgur.com/zenPw.png Within the structure, the api functions as a NestJS application while the data-access-scripts-execute ...

Using JavaScript, delete a class from an element

I am looking for a way to remove a specific class attribute from all elements on a webpage. The challenge is that I only have the class name as a reference, and cannot use any other identifiers like id or another class. Additionally, I cannot rely on JavaS ...

Node.js: Attempting to arrange ISO dates based on their time span

I am currently working on creating a line chart using the chart.js library. In order to do this, I have an array that contains ISO dates and my goal is to determine which ISO dates belong to the same hour and day. This information will then be used to gene ...

Issues with CSS properties not functioning correctly within the class.col function

When attempting to apply specific CSS properties to a particular area (e.g., "Dashboard") by assigning the class name "main" to the div.col function in the HTML, I encountered an issue where the CSS property applied affected the entire page. The following ...

Error Encountered in Next.js: PDFtron Webviewer - Troubleshooting

I'm currently working on a website that incorporates a dynamically imported PDF viewer within the page. When running the code locally, everything operates smoothly with no errors. However, when executing the "npm run build" command, I encounter the fo ...

The Node.js application successfully receives an emit event from the browser, however, the browser does not receive any emit

I'm having trouble understanding why the node.js server can connect and receive an emit() from the browser, but when I try to emit() back from node.js it doesn't reach the browser. Am I overlooking something here? The console log displays "Test ...

What is the best way to develop interactive components using Google App Scripts for Google Sites?

I am currently working on building dynamic app script components that can be seamlessly integrated into my website, each with unique data for every instance of the script. I initially attempted using parameters but I'm uncertain if this is the most ef ...

Storing information in local storage as JSON using AngularJS

I am working on a form with the following fields: <form ng-submit="addState()"> <input ng-model="text1" type="text"> <input ng-model="text2" type="text"> <input ng-model="text3" type="text"> ...

Error encountered while submitting ajax request to server

When I click a button, a function is triggered with the argument insertSongPlay(newSong.songID);. After logging the value of newSong.songID, which is 90 as desired, an ajax call is made: function insertSongPlay(songID) { $.ajax ({ type: " ...

What is the best way to connect a relative CSS stylesheet to a master page?

My Java application generates several HTML pages, organized in different directories: html_pages/ | ----> landin_page.html html_pages/details | ----> index1.html html_pages/more_details | ----> index2.html html_pages/css | ...

Trigger Angular Animation when there is a modification in the DOM element's appearance or styling

I've been working on implementing a fade-in animation in my Angular App that triggers every time the background changes, but I'm facing some challenges with it. Here's the relevant code snippet: HTML: <div @fadeIn [style.backgroundImag ...

The Ajax request was a success, but I am unable to retrieve radio button values from the $_POST variable

My website operates fully asynchronously, generating and destroying HTML elements on button clicks that prevent navigation. In this section, I am creating a form with an array of radio boxes for rating from 1 to 10. This form is submitted using jQuery.aja ...

Error: The "toString" property of an undefined variable cannot be read in uploadify

I'm having trouble with uploadify and trying to debug the issue. When attempting to use uploadify in Chrome, I encounter the following error: Uncaught TypeError: Cannot read property 'toString' of undefined Below is my html code: <li ...

The registration feature powered by JQuery is experiencing technical difficulties and not functioning

Having trouble with a registration system on my website at *. When someone registers, it should either show an error message or display "true" if the registration is successful. I have a javascript file (http://pastebin.com/mv9CWZcT) set up to redirect the ...

Finding the equivalent of BigInt from Javascript in C#

After creating a JavaScript script that converts a string to BigInt, I encountered a challenge while trying to find a C# equivalent function. The original conversion in Javascript looked like this: BigInt("0x40000000061c924300441104148028c80861190a0ca4088 ...

Attempting to modify PHP query following submission of data via Axios in Vue application

Fetching a JSON object through a PHP query from a service known as BullHorn can be done like this: <?php echo getBhQuery('search','JobOrder','isOpen:true','id,title,categories,dateAdded,externalCategoryID,employmentTy ...

transfer properties to a dynamic sub element

I am currently working on a multi-step form project. I have successfully implemented the form so that each step displays the corresponding form dynamically. However, I am facing challenges in passing props to these components in order to preserve the state ...

Utilizing Vuex to Access a Component's Property in Vue

Utilizing Vuex in my app is integral for executing asynchronous tasks, such as logging a user into the application. Upon successful login and execution of axios.then(), I aim to notify the component from which I invoked this.$store.dispatch('login&apo ...

Experiencing incorrect outcome when using the Number.isInteger() function in JavaScript

I have been experimenting with the Number.isInteger() method on the Chrome console. After running a for loop and checking the result using console.log(arr);, I noticed that the array only contains a single value of 1, like this: [1]; var arr = [1, 2, 3, ...