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

Leveraging ng-change in AngularJS when utilizing the "Controller As" syntax

Attempting to steer clear of using $scope within my controller function, I have instead chosen to use var viewModel = this; employing the "controller as" viewModel syntax. The issue at hand is that while I can access data from a service, invoking functio ...

Showcase pictures from a directory in real-time using a combination of jQuery and Bootstrap as the folder continues to fill up with images

Although I am just beginning to learn about UI, I have a question that seems important to me. In my application, there is a background thread that downloads images and saves them in a folder named "images". I want these images to be displayed in the UI as ...

Tips for implementing code to function across several images in HTML and CSS

Hey there, I'm currently working on a website project for my friend and I sometimes refer to www.w3schools.com for help with coding. I'm having trouble implementing a gallery feature where users can click on images to view them fullscreen. I foun ...

Adjust the width of a container to exceed 32767 using jquery in the Opera browser

I am looking to create a compact timeline using jQuery, and I want this timeline to have a width exceeding 32767 pixels. Interestingly, when I attempt to modify the width using the jQuery code $(".timelinecontainer").width(32767);, it doesn't seem to ...

Synchronizing timers among different elements

Just a little context: I'm diving into the world of React and currently working on a small app using next.js (with a template from a tutorial I followed some time ago). Lately, I've encountered a challenge where I need to synchronize a timer betw ...

Tips for enabling the background div to scroll while the modal is being displayed

When the shadow view modal pops up, I still want my background div to remain scrollable. Is there a way to achieve this? .main-wrapper { display: flex; flex-direction: column; flex-wrap: nowrap; width: 100%; height: 100%; overflow-x: hidden; ...

How to eliminate all <style> tags across the board using Regex in JavaScript

Is there a way to utilize regex in JavaScript for removing all instances of <style>, <style type="text/css">, </style>, and <style type="text/css"/>? I want the outcome to only present the CSS without any style tags. The code below ...

The issue with the <Button> component not properly linking in next.js

Having trouble with a button wrapped inside a custom Navbar component. The code snippet in question is: <NavBtn> <Link href="/contact" passHref> <Button> Contact Me </Button> </Link> & ...

Unable to input text using Python Selenium in a textbox

Currently, I am attempting to input text into a specific textarea HTML element using Python Selenium: <div class="spk-c spH-d"><div id="gwt-uid-23" class="sppb-a"> <div class="sppb-b spk-b">For example, flowers or used cars</div> & ...

"Complete with Style: Expand Your Horizons with Material-UI

The Autocomplete feature in Material UI is not expanding to the full width of the TextField element. Any suggestions on how to fix this issue? ...

What factors cause variations in script behavior related to the DOM across different browsers?

When looking at the code below, it's evident that its behavior can vary depending on the browser being used. It appears that there are instances where the DOM is not fully loaded despite using $(document).ready or similar checks. In Firefox, the "els ...

Can you explain the significance of this code snippet 'true <=> false'?

Today I came across this piece of code: true <=> false. I'm a bit confused by it and don't really understand how it works. If anyone could shed some light on this expression for me, I would greatly appreciate it. For reference, this code ...

What is the best way to send data from ajax to a django view?

I have a script for ajax that retrieves the public key and sends other details to the Stripe server for payment. However, I am struggling with sending the dynamic value of the price to item_line. fetch("/config/") .then((result) => { return re ...

SapUI5: Implementing a toggle functionality to display/hide one list item based on another list item's action

UI5 is a versatile framework with numerous possibilities, but sometimes I find myself struggling to implement ideas that would be easier in traditional HTML. Here's the scenario: I want to create a List with ListItems that display cities like Berlin, ...

Combining the power of MobileServiceClient and AngularJS for seamless integration

Exploring the WindowsAzure.MobileServiceClient integration with Angular for single sign-on and CRUD operations has been quite a journey for me as a newcomer to Angular. I am currently seeking the most effective approach to achieve this: Should I initiali ...

Finding a potential data breach in Node.js, MongoDB, and Chrome, exposed passwords are

My web app is built using nodejs with mongodb as the database backend, and I am encountering an issue with Chrome browser flagging my login process via passport.js as an exposed password. How can I prevent this warning? Should I implement something like Bc ...

``There seems to be a problem with the ngb time picker when using the up and

Currently, I am utilizing Bootstrap 4 and NG Bootstrap time picker for a project in Angular 10. Despite correctly adding all the code, I have encountered an issue where the up and down arrows on the time picker are not functioning as expected. Below is a s ...

Retrieve the encrypted URL

I'm facing an issue with extracting parameters from an encrypted URL. When using the queryparams function, it only retrieves a portion of the URL after being decrypted. For instance, consider this example URL: http://localhost:4200/househouse? MGRjYjQ ...

What is the reason for the countdown number's color remaining the same even after it reaches a specific time threshold?

Creating a simple countdown for sports was my idea, but now I'm stuck on the "changeColor" part that I don't have enough knowledge about. The countdown is functioning perfectly, but customizing the colors and adding CSS animations seems challeng ...

Looking to transform a nested JSON structure into a visually appealing HTML table with merged rows?

My JSON structure appears as follows: $scope.data = [ { "type":"Internal", "count": 3, "library" : [ { "type":"Library 123", "count": 2, "version" ...