The navigation controller, responsible for updating navbar values, is only executed once

My goal is to construct a simple Angular application and familiarize myself with the basics.

To start, I'm utilizing Yeoman's angular-generator for scaffolding. This generator comes with a predetermined .config featuring $routeProvider, which I tweaked to suit my requirements:

angular
  .module('raidersApp', [
    'ngRoute',
    'ngTouch'
  ])
  .config(function ($routeProvider) {
    $routeProvider
      .when('/:langID/:proverbID', {
        templateUrl: 'views/proverb.html',
        controller: 'ProverbCtrl'
      })
      .when('/:langID', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl'
      })
      .otherwise({
        redirectTo: '/en'
      });
  });

In order to maintain organization, I've designed several templates that will be included in my app's index.html:

<header class="header" ng-controller="HeaderCtrl">
  <div ng-include="'views/header.html'"></div>
</header>

<main class="container">
  <div ng-view=""></div>
</main>

<footer class="footer">
  <div ng-include="'views/footer.html'"></div>
</footer>

Within the header view, there is a Bootstrap navbar that requires dynamic content based on user input. The ID of the selected language is obtained using $routeParams:

<li class="dropdown">
  <a href class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{langID}}<span class="caret"></span></a>
  <ul class="dropdown-menu" role="menu">
    <li><a href="#/{{language}}" ng-repeat="language in languages">{{language}}</a></li>
  </ul>
</li>

To ensure this value can be accessed by multiple controllers, I created a data factory:

angular.module('raidersApp')
  .factory('data', function () {

    var langID = "en";

    return {
      getLang: function() {
        return langID;
      },
      setLang: function(newlangID) {
        langID = newlangID;
      }
    }

  });

I developed a separate controller, HeaderCtrl, to manage the navbar:

angular.module('raidersApp')
  .controller('HeaderCtrl', function (data, $http, $scope, $routeParams) {
    $scope.langID = data.getLang();
    $scope.languages = [
      'en',
      'pt',
      'se'
    ];
  });

However, the controller is only invoked once. As a result, the default language (in this case, "en") remains static in the dropdown menu.

While the rest of the functionality works as intended, including URL navigation and language updates in the main controller via $routeParams, the issue lies specifically with the header controller.

One potential explanation could be that the HeaderCtrl is defined outside the ng-view scope in the index.html, causing it to be disregarded by the $routeProvider.

How can I address this dilemma without duplicating the navbar across all views?

I considered incorporating ng-include in each template, but this approach feels inelegant. Are there cleaner or more sophisticated solutions available?

Answer №1

To update your controller, modify this line:

$scope.langID = data.getLang();

to

$scope.langID = function () {
    return data.getLang();
}

Next, adjust the binding in your header to:

{{langID()}}

This will ensure that it fetches the latest value from the factory during every $digest.

The issue lies in the controller setting $scope.langID to the initial value of data.getLang(). Although data.getLang() may change over time, the scope variable remains stagnant. By encapsulating it within a function, you can resolve this inconsistency.

Answer №2

In order to ensure that the $scope.language property is always updated when the value changes, one approach would be to utilize a $watch on the value within the factory. This way, whenever the value changes, the header controller can immediately retrieve the new value. Below is an example of how you can achieve this:

HTML:

<div ng-controller="HeaderCtrl">Language: {{language}}</div>
<div ng-controller="MainCtrl"><button ng-click="randomNum()">Set</button></div>

JS:

app.controller('MainCtrl', function($scope, myFactory) {
  $scope.randomNum = function() {
    myFactory.set(Math.random())
    console.log(myFactory.get())
  }

});

app.controller('HeaderCtrl', function($scope, myFactory) {
  $scope.language ='';
  $scope.$watch(function() {
    return myFactory.get()}, 
    function(newVal, oldVal) {
      if(newVal != oldVal) {
        $scope.language = newVal;
      }
    })

})

app.factory('myFactory', function() {
  var myVal = '';
  return {
    get: function() {
      return myVal;
    },
    set: function(val) {
      myVal = val;
    }
  }
})

The code snippet above demonstrates how clicking the button in MainCtrl will generate a random value and assign it to the factory's myVal. However, without manual intervention or setting up an interval (not recommended), HeaderCtrl won't automatically detect these changes. By implementing a $watch function, we can monitor for any modifications to the factory's value and take appropriate action when needed.

Another approach could involve using $rootScope.$broadcast from the first controller while establishing a $scope.$on listener in the second controller. This setup would prompt the listener to fetch the latest value from the factory upon activation.

Both solutions are viable options, but the proposed method here involves less code complexity. Feel free to check out the Demo for a hands-on experience with this implementation.

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

Dealing with extended render times in React applications

Currently, I'm working with a limited set of 100 documents per page and utilizing a wrapper component for certain conditional actions. const onClickCheckbox = (order: OrderProps) => { const _ordersToExport = [...ordersToExport]; const ind ...

having trouble adjusting the width of the buefy modal

Currently, I am working with vuejs alongside bulma and buefy. Specifically, I am utilizing the buefy modal feature and attempting to customize the modal width by utilizing its 'width' property. Thus far, I have attempted specifying the width in t ...

AngularJS - Controller routing to open link in new tab based on condition

Within my application, there are two distinct types of profiles available for organisations. When a user interacts with a profile name, the system must first determine if a premium profile exists for that organisation. If a premium profile is found, the us ...

Unresolved issue with Jade in Angular Routing

Currently, I am working on building a web server using expressjs and jade for the frontend. I have also implemented client-side routing with angularjs but unfortunately, my UI is not displaying as expected. Below you can find my code and the unexpected out ...

Utilizing Conditional Styling for an Array of Objects within a Textarea in Angular 6

My array contains objects structured as follows: list =[ { name:"name1", value:true } { name:"name2", value:false } { name:"name3", value:true } { name:"name4", value:false ...

ACL - Utilize ACL in conjunction with the passport authentication system

I am experimenting with node_acl in combination with passport-local. Unfortunately, I am facing an issue when trying to secure the route for the admin-user '/admin', as it keeps redirecting me to the /login page. Below is a simplified version of ...

Why isn't the router returning JSON data?

Why am I not receiving a response from this code? const express = require('express') const mongoose = require('mongoose') const authRouter = require('./authRouter') //importing the router const PORT = process.env.PORT || 3000 ...

What methods and technologies are accessible for executing JavaScript through PHP?

Are there any frameworks or tools available to execute JavaScript from PHP? Is there a similar project like the Harmony project for PHP? I am interested in running JS unit tests (or even BDD) directly from PHP, as demonstrated in this post (for Ruby). Am ...

Attempting to create a fixed div at a specific position, however, an unexpected Uncaught TypeError disrupted additional code functionality

Is there a way to make a div stay fixed in place while scrolling, but then unstick at a specific point? I found some code that seemed to work for this purpose, but unfortunately it caused an error that affected other jQuery scripts. The console displayed t ...

Employing CSS animations to elevate div elements

Currently, I am working on animating a table of divs and trying to achieve an effect where a new div enters and "bumps up" the existing ones. In my current setup, Message i3 is overlapping Message 2 instead of bumping it up. How can I make Messages 1 and 2 ...

Exploring Techniques for Adjusting Website to User's Screen Resolution

My website is currently designed for a screen resolution of 1024x768. However, I am aware that when viewed on computers with smaller or larger screen resolutions, the layout starts to distort. Is there a way to make the website adaptable to any user&apos ...

Utilize Node.js and an API to generate a new problem in GitHub, but encountering an issue where the response

I have been experiencing an issue related to making a Post request to the Github API for creating an issue. I have gone through this post on Stack Overflow but I am seeking assistance in using the request module. Although I have referred to the Github docu ...

Unable to display content when the button is triggered

I am facing an issue with hiding a div (class="login-form") and displaying it only after clicking the Login button on my HTML page using jQuery. However, despite clicking the button, the login form does not appear. Can anyone help me understand why this ha ...

Is JQuery the ultimate solution for creating a dynamic multi-language website?

Embarking on a new project that requires support for multiple languages. My plan is to create a jQuery/AJAX based application with all the code in jQuery, simply calling JSONs for data. What would be the most effective approach for implementing multi-lan ...

Unable to utilize the .keyCode method within a query selector

Trying to utilize .keyCode in JavaScript to identify a pressed key, but the console consistently displays null after each key press. Below is the relevant CSS code: <audio data-key="65" src="sounds\crash.mp3"></audio> ...

Formatting numbers as floating point values in AngularJS

I need a text box where users can enter an amount. The input should be restricted to numbers only, with no special characters or decimal points. I have managed this using custom filters. However, I also need the entered number to automatically display as ...

"Using NgRepeat with multiple filters and the track by option can impact the length of the resulting

Imagine having an ng-repeat like <li ng-repeat="event in eventData | filter:search | customFilter1:someData | customFilter2:someData | orderBy:predicate:reverse | limitTo:quantity track by id">{{event.someAttribute}}</li> If you want to sho ...

Express encountered an issue when trying to upload a file through AngularJS

I am currently facing an issue with uploading a file to express and subsequently to mongoDB. Despite my efforts, when I attempt to upload the file to express, it appears that no data is being passed through the response. I am utilizing ng-file-upload.min. ...

Verify if the ajax request does not contain any data

Utilizing the complimentary geocoding API provided by MapQuest I'm attempting to verify the success of a request that returned no data. Entering "vdfsbvdf54vdfd" (a nonsensical string) as an address in a form field, I anticipate receiving an alert s ...

Error in Node.js React: Unable to add context property as the object is not extendible

Currently, I'm in the process of integrating an isomorphic react component into my node.js + express setup. However, as I attempt to add the component to my jade template for rendering, I encounter this error: TypeError: Can't add property contex ...