0

I am working on a legacy system that uses jQuery and had to add AngularJS for a particular feature, however im having issues updating the scope.

Basically, we have a dropdown and when you select an option, we're firing an Ajax call to get an array or objects. This array of objects is then being stored in a global variable, say var myObjs. Basically using the ng-repeat service from Angular, I need to loop through these and render a list.

I am new to Angular, so i'm not sure if this is the way to be done. What I am doing is setting the scope in this way:

$scope.myObjs= myObjs;

However, by doing so, the scope is not changing at all.

Can someone tell me how this can be done? I tried to look around but am finding it a bit hacky having a hybrid of AngularJS & jQuery on the same page.

EDIT: adding sample snippet. Basically on change of the dropdown im firing an ajax call, and store the response (which is an array of objects) in myObjs variable. Then I am trying to set the scope to the value of this variable. Regarding the way I am bootstrapping Angular, this is due to a limitation of the legacy system, which is over 8 years old.

var myObjs = null;


$(function() {
  $("#myHeader").on("change", "#mySelect", function() {
    // perform Ajax Call
  });

});

function ajaxCallback(data) {
  myObjs = data;
}

var myModule = angular.module("GetObjsModule", []);
myModule.controller("MyController", function($scope) {
  $scope.objs = myObjs;
});

angular.element(document).ready(function() {
  var myDiv = $("#myDiv");
  angular.bootstrap(myDiv, ["GetObjsModule"]);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
</script>

<div id="myHeader">
  <select id="mySelect">
    <option value="1">Value 1</option>
    <option value="2">Value 2</option>
    <option value="3">Value 3</option>
  </select>
</div>

<div id="myDiv">
  <ul id="myList" ng-controller="MyController">
    <li ng-repeat="x in objs">
      <div class="accordionHeader">
        {{x.name}} {{x.surname}}: {{x.tel}}
      </div>
      <div>
        <p>
          Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut odio. Curabitur malesuada. Vestibulum
          a velit eu ante scelerisque vulputate.
        </p>
      </div>
    </li>
  </ul>
</div>

8
  • Can you show your code plz? Commented May 29, 2015 at 10:12
  • If you are not using an angularjs service (ie $http etc) you are going to be executing outside the angular digest cycle, you need to trigger a cycle after changing the scope: ie $scope.$apply() Commented May 29, 2015 at 10:14
  • @PatrickEvans indeed we are not using the $http service. Commented May 29, 2015 at 10:19
  • @PatrickEvans so you mean like this: $scope.myObjs= myObjs; $scope.$apply(); ? Commented May 29, 2015 at 10:26
  • @Zee I added a snippet Commented May 29, 2015 at 11:05

2 Answers 2

1

Give an id for the ul <ul id="Mylist"> and add the below code in your callback function.

 angular.element(document.getElementById('Mylist')).scope().$apply(function(scope){
     scope.objs = myObjs;
});
Sign up to request clarification or add additional context in comments.

1 Comment

that worked out. The only issue im having now is that the accordions are not being rendered properly like the jQuery accordions. Having all divs visible. I added the following after setting the scope: $("#myList").accordion({ header: ".accordionHeader", });
1

It's pretty hard to come from jQuery and handle Angular's way of thinking.

Basically, to achieve what you want, you don't need jQuery at all.

<div ng-controller="MyController">
<div id="myHeader">
  <select id="mySelect" ng-change="yourUpdateFunction()">
    <option value="1">Value 1</option>
    <option value="2">Value 2</option>
    <option value="3">Value 3</option>
  </select>
</div>

<div id="myDiv" ng-show="requestLoaded">
  <ul>
    <li ng-repeat="x in objs">
      <div>
        {{x.name}} {{x.surname}}: {{x.tel}}
      </div>
      <div>
        <p>
          Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut odio. Curabitur malesuada. Vestibulum
          a velit eu ante scelerisque vulputate.
        </p>
      </div>
    </li>
  </ul>
</div>
</div>

So basically :

  1. I wrapped your code into a div, which will contain your controller
  2. I used ngChange directive to run an update function on your select element

Then, the JS part :

var myApp = angular.module("myApp", []);
myApp.controller("MyController", function($scope, $http) {
  $scope.objs;
  $scope.requestLoaded = false;
  $scope.yourUpdateFunction = function () {
     // Here you can run a $http request, based on value of select.
     $http.get('/someUrl').success(function(data, status, headers, config) {
       $scope.objs = data;
       $scope.requestLoaded = true;
  });
  }
});

In a nutshell : $scope.yourUpdateFunction is run on change on your select element (ngChange directive). It performs an asynchronous http request and set its response data to $scope.objs (so, from now, you can display it in the view). Then, the $scope.requestLoaded is used to show / hide your list. When the http request is loading, its false, the list is hidden, when it's done, the list is displayed, it's the directive ngShow.

It's a basic example, but this way you can achieve what you want.

Remember that AngularJS provides a two-way data binding, whenever you change something in the view, it gets updated in the controller, and vice versa.

3 Comments

thanks for feedback. In the ideal world, this would work great :) The issue i'm having is that I cannot use the $http service as I need to use a custom one that was written as part of this legacy system. To give you a clearer idea, this is very close to what I am after: plnkr.co/edit/uN4QF8kVoLPYrcPar5l2?p=preview . However I want that when I have the ajax callback and I update the variable data, this gets reflected in the HTML as well (basically updates the scope). Any idea if this is possible? Kind of triggering an update as soon as the var data is updated..
You can drop jquery ajax into the mix if you want, you just have to make sure you start the digest cycle when it completes.
Yes you can use jquery Ajax methods or pure JS solution to get your content. Remember that whenever you update your scope variable in the controller, it gets updated in the view. So even if you don't use Angular http method, the two-way binding thing will work.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.