Is it possible to alter the parent scope from an AngularJS directive?

I am currently in the process of constructing my initial Angular application, but I am encountering some difficulties while attempting to achieve a specific functionality. The issue revolves around a video container which is supposed to remain hidden until $scope.video.show = true; I aim to alter this value upon clicking on a particular link by implementing it within a directive. Any assistance or guidance in this matter would be greatly appreciated.

html:

<div ng-controller="AppCtrl">
    <div ng-cloak 
         ng-class="{'show':video.show, 'hide':!video.show}">
                  // youtube iframe content, for example
    </div>

    <div>
        <ul>
            <li>
                <h3>Video Headline 1</h3>
                <button type="button" 
                    video-show 
                    data-video-id="jR4lLJu_-wE">PLAY NOW&nbsp;&rang;</button>
            </li>
            <li>
                <h3>Video Headline 2</h3>
                <button type="button" 
                    video-show 
                    data-video-id="sd0f9as8df7">PLAY NOW&nbsp;&rang;</button>
            </li>
        </ul>
    </div>
</div>

Javascript:

var angularApp = angular.module("savings-video", [])
.controller('SavingsVideoController', function($scope) {

    $scope.video = {
        show : false,
        videoId : ""
    };
};

angularApp.directive("videoShow", function(){
    return{
        restrict: 'A',
        link: function(scope , element){

            element.bind("click", function(e){

                var $selectedElement = angular.element(element);
                $selectedElement.closest('li').siblings().addClass('hide');   // hide the other one
                $selectedElement.closest('li').removeClass('hide');           // keep me open

                scope.video.show = true;  // struggling to make it work
                     // what is the optimal approach to accomplish this?

            });
        }
    }
});

Answer №1

There are several ways you can enhance your code.

  1. Consider exploring ngShow/ngHide and ngIf; they offer a more straightforward toggle functionality compared to manual implementation.
  2. Adopt an Angular mindset. Instead of manipulating the DOM directly, define your rules using angular directives for easier management.

For instance, consider implementing it this way:

<div ng-controller="AppCtrl">
    <div ng-cloak ng-show='video.show">
              // youtube iframe content, for example
    </div>

    <div>
        <ul ng-switch="video.videoId">
            <my-video my-video-id="jR4ABCD" my-headline="Video Headline 1" ng-switch-when="myVideoId" my-video-manager="video" />
            <my-video my-video-id="al1jd89" my-headline="Video Headline 2" ng-switch-when="myVideoId" my-video-manager="video"/>
        </ul>
    </div>
</div>

In this updated version, the iframe is conditionally displayed using ngShow, and ngSwitch controls which video appears based on $scope's video.videoId. Additionally, the list items have been transformed into a directive called my-video.

thisViewModel.directive("my-video", function(){
    return{
        restrict: 'E',
        replace: true,
        scope: {
           myVideoId = "=",
           myHeadline = "=",
           myVideoManager = "="
        },
        template = '<li><h3>{{myHeadline}}</h3><button type="button" ng-click="play()">PLAY NOW&nbsp;&rang;</button></li>',
        link: function(scope , element){
            scope.play = function(){
                 myVideoManager.show = true;
                /*whatever you want here, using scope.myVideoId*/
            }
        }
    }
});

This directive achieves the same result as the original HTML but within the angular framework, simplifying access to the desired properties. By leveraging angular directives, the need for manual UI logic is eliminated, resulting in cleaner HTML and JavaScript. While there is room for further optimization, this approach aligns better with best practices.

It may take some time to master, but referring to the guidelines provided in the linked Stack Overflow post can be beneficial.

UPDATE

I overlooked a requirement previously. If you want both videos to display when none is selected, avoid using ng-switch and opt for manual ng-show declarations instead.

<div>
        <ul>
            <my-video my-video-id="jR4ABCD" my-headline="Video Headline 1" ng-show="myVideoId == video.videoId" my-video-manager="video" />
            <my-video my-video-id="al1jd89" my-headline="Video Headline 2" ng-show="myVideoId == video.videoId" my-video-manager="video"/>
        </ul>
    </div>

Since ng-switch essentially equates to ng-show, the logic transitioned to the ng-show attribute in this scenario.

Moreover, if you have a collection of videos, explore ng-repeat for automatic repetition of the video tag instead of manual duplication.

<ul>
   <my-video ng-repeat='aVideo in myVideoArray' my-video-id='aVideo.videoId' my-headline...(and so on)>
</ul>

Answer №2

It seems like there is an issue with the controller names not matching up in your code. Consider updating AppCtrl to SavingsVideoController to resolve this discrepancy.

Answer №3

You simply require a straightforward solution.

HTML

<div ng-controller="AppCtrl">
    <div ng-cloak ng-show="view.show">
        <!-- Using ng-show is more convenient -->
    </div>

    <div>
        <ul>
            <li>
                <h3>Video Headline 1</h3>
                <button type="button" 
                    ng-click="view.show = true"
                    data-video-id="jR4lLJu_-wE">PLAY NOW&nbsp;&rang;</button>
                    <!-- Extra directive not required to change view.show -->
            </li>
            <li>
                <h3>Video Headline 2</h3>
                <button type="button" 
                    ng-click="view.show = true"
                    data-video-id="sd0f9as8df7">PLAY NOW&nbsp;&rang;</button>
            </li>
        </ul>
    </div>
</div>

JS

var thisViewModel = angular.module("savings-video", [])
.controller('SavingsVideoController', function($scope) {

    $scope.video = {
        show : false,
        videoId : ""
    };
};

// No need for creating another directive

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

detect mouse click coordinates within an iframe that spans multiple domains

I am currently encountering an issue with tracking click position over a cross-domain iframe. Here is my current code: <div class="poin"> <iframe width="640" height="360" src="http://cross_domain" frameborder="0" allowfullscreen id="video">< ...

converting JSON to date format in angular

.controller('feedCtrl', ['$scope', '$http', function($scope, $http) { $http.get('items.json').then(function(response) { $scope.items = response.data; $scope.user = localStorage.getItem("glittrLoggedin"); ...

Decomposing a Vue.js API response into multiple variables

Utilizing vue to send http requests and store data in variables can be done like so: the api response will have the following structure: data: data: [id:1... etc] function: fetchOffers() { this.$http.get('http://127.0.0.1:8000/api/of ...

What is the best way to arrange elements based on the numeric value of a data attribute?

Is there a way to arrange elements with the attribute data-percentage in ascending order, with the lowest value first, using JavaScript or jQuery? HTML: <div class="testWrapper"> <div class="test" data-percentage="30&qu ...

Incorporating TypeScript with jQuery for efficient AJAX operations

I recently added jQuery typings to my TypeScript project. I am able to type $.ajax(...) without encountering any compile errors in VS Code. However, when I test it on localhost, I receive an error stating that "$ is not defined." In an attempt to address t ...

Developing an interactive input field using JavaScript's Document Object Model (DOM)

I am struggling with creating an editable text field using JavaScript. I have come across a function that allows for editing, but I am unsure if it is possible to change the title from High School to Middle School, which is generated by the function create ...

Creating a Javascript object from a JSON string

Looking for a way to convert a JSON string into a JavaScript object? You can make use of the following code snippet obtained from the server: JSON String: ["{"title":"Admin Dhaka","href":"#0","dataAttrs":[],"data":["{\"title\":\"BNS HAJI M ...

Looking for a solution to toggle the visibility of a div based on whether search results are found or not using JavaScript

Running this code <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Searc ...

Test your knowledge of Javascript with this innerHtml quiz and see

How can I display the output of a score from a three button radio button quiz without using an alert popup? I want the output to be displayed within a modal for a cleaner look. I tried using InnerHTML but now there is no output when the button is clicked. ...

One way to filter using a single array

Currently testing some angularJS with this particular example http://www.w3schools.com/angular/tryit.asp?filename=try_ng_filters_filter <ul> <li ng-repeat="x in names | filter : 'i'"> {{ x }} </li> </ul> Is ther ...

Extract the URL from an AJAX request within an IFRAME using a Chrome Extension

Currently, I am facing the following issue: I am trying to develop a Chrome extension, but encountering some major obstacles: The page I am working with loads an iframe. This iframe contains JavaScript code that triggers an AJAX request which returns an ...

Exploring the capabilities of an Angular factory

I am facing challenges in improving the unit test coverage of an Angular project, particularly when trying to test an AngularJS factory with multiple dependencies. The factory I am working on has 5 dependencies, and I am struggling to even write a basic t ...

When working with Node.js and Express, I encountered an issue where the req.session object was not defined within

It's peculiar to me that req.session.username is undefined in the tag >>>DOESNT WORK<<< while it works in the tag >>>THIS DOES WORK<<<. I passed req as an argument to my module, but it seems like there might be some ...

Keeping the Bootstrap popover anchored to the content

I have a functional bootstrap popover that includes a time attribute. However, I am looking to enhance its functionality so that it remains open when the mouse is on the content and closes only when the mouse leaves the content. Here is the relevant code ...

Attempting to decode the string prior to selecting an item from the Vue.js/Nuxt array

Hey there, I really appreciate anyone who can assist me with this. I've been dabbling in Laravel for a few months and now I'm trying to dive into studying Nuxt. The specific type of translation I need help with is proving to be quite challenging ...

Having trouble getting a div to slide to the left on hover and collapse on mouseout using Jquery?

Hey there! I need some assistance in completing this code snippet. I have a div with overflow:hidden and a margin-left of 82px. Inside it, there is a share link and a ul list containing three external links. When I hover over the share link, everything w ...

Encountering a JS error that states: "Uncaught SyntaxError: missing ) after argument list" when running the following code

I keep encountering the error message: "Uncaught SyntaxError: missing ) after argument list" when I try to call the delete function within the createHtmlview function. console.log("Delete Item is being called") } ...

jQuery is not updating the div as expected

While typing out this question, I'm hoping to uncover a solution that has eluded me so far. However, just in case... About a year ago, I successfully implemented something similar on another website and went through the code meticulously. Surprisingl ...

Accessing a peaceful API and displaying the outcome on a webpage using Node.js

I am currently working on a project that involves fetching data from a RESTful API and displaying the results on an HTML webpage using Node.js. While my code is running smoothly, I would like to ensure that the RESTful request is made every time the webp ...

Executing JavaScript with Python in Selenium

Completely new to Selenium. I need help running a javascript snippet in this code (as commented), but struggling to do so. from selenium import webdriver import selenium from selenium.common.exceptions import NoSuchElementException from selenium.webdriver ...