$scope updates not shown in Angularjs - javascript

$scope doesn't seems to sync with updates in Angularjs.
I update my time values (myst and myet) using ui.bootstrap.timepicker, then when I display userscheds[index] using alert(JSON.stringify($scope.userscheds[index]));, only the original values are displayed. Something I'm missing?
Any help would be appreciated
See my plunker or code below
update #1
Comment from #dgig to remove this. in ng-model="this.myst". Changed to ng-model="myst"
But my $scope still not shown with the updates done
html modal
<div class="container" ng-app="appUserSchedule">
<div ng-controller="CtrlUserSchedule" >
<div class="row">
<ul>
<li ng-repeat="x in userscheds">{{x.week_day}} {{x.time_start}}-{{x.time_end}}
<span ng-click="ctrl.showModal($index)" style="cursor:pointer;">Edit</span>
<span ng-click="ctrl.removeItem($index)" style="cursor:pointer;">Delete</span>
</li>
</ul>
</div>
<!-- Modal -->
<script type="text/ng-template" id="modalContent.html">
<div class="modal-body">
<div class="row">
<div class="col-sm-6">
<timepicker ng-model="myst" hour-step="1" minute-step="15" show-meridian="true"></timepicker>
</div>
<div class="col-sm-6">
<timepicker ng-model="myet" hour-step="1" minute-step="15" show-meridian="true"></timepicker>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="$close()">OK</button>
<button class="btn btn-primary" ng-click="saveUserScheduleEntry()">Save</button>
</div>
js
var app = angular.module("appUserSchedule", ['ui.bootstrap']);
app.controller("CtrlUserSchedule", function($scope,$http,$location,$modal) {
$scope.ctrl = this;
$http.get('userschedule.json').success(function(data, status, headers, config) {
$scope.userscheds = data.userschedules;
//console.log(data);
}).error(function(data, status, headers, config) {
console.log("No data found..");
});
// Show modal
this.showModal = function (index) {
var modalInstance;
modalInstance = $modal.open({
templateUrl: 'modalContent.html',
controller: 'CtrlUserSchedule',
scope: $scope
});
objts = new Date($scope.userscheds[index].datetime_start);
objte = new Date($scope.userscheds[index].datetime_end);
$scope.myst = objts;
$scope.myet = objte;
// Save User Schedule Entry details after making a change, then close modal
$scope.saveUserScheduleEntry = function() {
// Displays original value, but where are my updated values?
alert(JSON.stringify($scope.userscheds[index]));
$http.put('userschedule.json',index).success(function(eventsuccess){
}).error(function(err){
/* do something with errors */
});
modalInstance.close();
};
}
json
{
"userschedules":[
{
"id":1,
"week_day":"Monday",
"datetime_start":"2016-03-08T08:00:00-05:00",
"datetime_end":"2016-03-08T12:00:00-05:00",
"time_start":"08:00",
"time_end":"12:00"
},
{
"id":21,
"week_day":"Monday",
"datetime_start":"2016-03-08T13:00:00-05:00",
"datetime_end":"2016-03-08T17:00:00-05:00",
"time_start":"13:00",
"time_end":"17:00"
}, ...

Related

nested ng-repeat with json and rest api call back

I am trying to make a UI using list of product in a json(products.json) file on local and their availability in number from wp rest api call back in html(ionic) I have this:
Controller:
.controller('ShopCtrl', function($scope, $ionicActionSheet, BackendService, CartService, $http, $sce ) {
$scope.siteCategories = [];
$scope.cart = CartService.loadCart();
$scope.doRefresh = function(){
BackendService.getProducts()
.success(function(newItems) {
$scope.products = newItems;
console.log($scope.products);
})
.finally(function() {
// Stop the ion-refresher from spinning (not needed in this view)
$scope.$broadcast('scroll.refreshComplete');
});
};
$http.get("http://example.com/wp-json/wp/v2/categories/").then(
function(returnedData){
$scope.siteCategories = returnedData.data;
console.log($scope.siteCategories);
}, function(err){
console.log(err);
});
Template view:
<div ng-repeat = "product in products">
<div class="item item-image" style="position:relative;">
<img ng-src="{{product.image}}">
<div ng-repeat = "siteCategory in siteCategories">-->
<button class="button button-positive product-price" ng-click="addProduct(product)">
<p class="white-color product-price-price">post <b>{{siteCategory[$index].count}}</b></p>
</button>
</div>
</div>
<div class="item ui-gradient-deepblue">
<h2 class="title white-color sans-pro-light">{{product.title}} </h2>
</div>
<div class="item item-body">
{{product.description}}
</div>
</div>
so how can I achieve that? I tried to use nested ng-repeat but it didn't work out.

How to properly use the same AngularJS 1.5 component multiple times in a view?

I'm creating a set of widgets with AngularJS 1.5's new components. The problem is, when using the same widget multiple times, they somehow share their controller or scope. I thought one of the things about components was that their scope is completely isolated?
My main html template which hold the widgets:
<widget-list
title="Books"
class="col-xs-12 col-md-4">
</widget-list>
<widget-list
title="Movies"
class="col-xs-12 col-md-4">
</widget-list>
<widget-list
title="Albums"
class="col-xs-12 col-md-4">
</widget-list>
My widget template:
<div class="widget widget-list">
<div class="panel b-a">
<div class="panel-heading b-b b-light">
<h5>{{$widget.title}}</h5>
<div class="pull-right">
<button type="button" class="btn btn-default btn-sm" ng-click="$widget.doSomething()">
Do something
</button>
</div>
</div>
<div class="panel-content">
{{$widget.content || 'No content'}}
</div>
</div>
</div>
My widget component:
app.component('widgetList', {
templateUrl: 'template/widget/widget-list.html',
bindings: {
title : '#',
},
controllerAs: '$widget',
controller: function($timeout) {
$widget = this;
console.log('Title on init: ', $widget.title)
$timeout(function() {
console.log('Title after 3 seconds: ', $widget.title)
}, 3000)
$widget.doSomething = function() {
$widget.content = "Something";
}
}
});
When running my code, this is what my console looks like:
Title on init: Books
Title on init: Movies
Title on init: Albums
(3) Title after 3 seconds: Albums
Also after rendering, all three widgets display No content in their template. But, when clicking the doSomething() button in either one of the three widgets, only the content of the last widget updates to Something.
What is happening here? Why are my components not 'isolated'?
Looks like you have a global variable called $widget here, try this:
var $widget = this;
instead of
$widget = this;
It creates a mess since the $widget variable holds a reference to the controller that has been recently initialized, in this case to the controller of the third component.
The problem with your code is that you are declaring the $widget on window scope, that's why your controller prints the last value, bacause it was being overridden every time the controller was getting instantiated. Use a var $widget instead and your code will work fine.
The following snippet solves this issue:
angular.module('app', [])
.component('widgetList', {
templateUrl: 'template/widget/widget-list.html',
bindings: {
title: '#',
},
controllerAs: '$widget',
controller: WidgetListController
});
function WidgetListController($timeout) {
var $widget = this;
console.log('Title on init: ', $widget.title)
$timeout(function() {
console.log('Title after 3 seconds: ', $widget.title)
}, 3000)
$widget.doSomething = function() {
$widget.content = "Something";
}
}
angular.element(document).ready(function() {
angular.bootstrap(document, ['app']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular.min.js"></script>
<widget-list title="Books" class="col-xs-12 col-md-4">
</widget-list>
<widget-list title="Movies" class="col-xs-12 col-md-4">
</widget-list>
<widget-list title="Albums" class="col-xs-12 col-md-4">
</widget-list>
<script type="text/ng-template" id="template/widget/widget-list.html">
<div class="widget widget-list">
<div class="panel b-a">
<div class="panel-heading b-b b-light">
<h5>{{$widget.title}}</h5>
<div class="pull-right">
<button type="button" class="btn btn-default btn-sm" ng-click="$widget.doSomething()">
Do something
</button>
</div>
</div>
<div class="panel-content">
{{$widget.content || 'No content'}}
</div>
</div>
</div>
</script>

How update list in AngularJS?

I created one TODO List in AngularJS but I didn't finish the update function. I have some difficulty.
How do I create the update function?
Link: https://plnkr.co/edit/XfWoGVrEBqSl6as0JatS?p=preview
<ul class="list-todo">
<li ng-repeat="t in tasks track by $index">
<div class="row">
<div class="six columns">
<p>{{ t }}</p>
</div>
<div class="three columns">
<button class="button" ng-click="update()">update</button>
</div>
<div class="three columns">
<button class="button" ng-click="delete()">x</button>
</div>
</div>
</li>
</ul>
Angular Code:
angular.module('todoTest', [])
.controller('todoController', function($scope) {
$scope.tasks = [];
$scope.add = function() {
$scope.tasks.push($scope.dotask);
}
$scope.update = function(){
$apply.tasks.push($scope.dotask);
}
$scope.delete = function() {
$scope.tasks.splice(this.$index, 1);
}
})
If you want to update the value you have to pass as parameter the position of the task inside the tasks array ($index is the position):
<button class="button" ng-click="update($index)">update</button>
And then the update function would be:
$scope.update = function(index){
$scope.tasks[index] = $scope.dotask;
}
Is that what you needed?
Button for updating. Visible only while updating.
<div class="row">
<button type="submit" class="u-full-width button button-primary">Criar Tarefa</button>
<button ng-show="updateMode" ng-click="update()" type="button" class="u-full-width button button-primary">Update</button>
</div>
New update function.
$scope.update = function(index) {
if ($scope.updateMode) {
$scope.tasks[$scope.updateIndex] = $scope.dotask;
$scope.updateMode = false;
} else {
$scope.dotask = $scope.tasks[index];
$scope.updateMode = true;
$scope.updateIndex = index;
}
If you click update on the task it will make the big update button visible and bring the old todo to the input. After hitting the big update button the todo task will update.
Plunker

How do I refresh my ng-repeat?

I have a controller (called "catalogueController") that manages my search box and my search page. I have the controller initially set the page to automatically call the search function defined in "catalogueController" when the app loads to pre-load my array of items (called Inventory) to be repeated via ng-repeat in the page.
The process runs like this:
1. I submit the search form.
2. "catalogueController" will send the search term to my factory (called "Search").
3. "Search" will have a function which will make a server call to query my database for that particular search.
4. The database will send the results of the search to the "Search" factory.
5. The "Search" factory will send the results to the "catalogueController" controller.
6. "catalogueController" will update the $scope.Inventory to be equal to the new result that I was received.
My problem is that ng-repeat does not refresh itself to display my new and updated $scope.Inventory array. $scope.Inventory definitely is updated (I have made sure of this through various console logs).
I have also tried to use $scope.$apply(). It did not work for me.
Thank you in advance for your help!
Here is my code:
HTML Template
<form role="search" class="navbar-form navbar-left" ng-controller="catalogueController" ng-submit="search(search_term)">
<div class="form-group">
<input type="text" placeholder="Search" class="form-control" ng-model="search_term">
</div>
<button type="submit" class="btn btn-default">Search</button>
</form>
<main ng-view></main>
catalogue.html partial
<div id="main" class="margin-top-50 clearfix container">
<div ng-repeat="items in inventory" class="row-fluid">
<div class="col-sm-6 col-md-3">
<div class="thumbnail"><img src="image.jpg" alt="..." class="col-md-12">
<div class="caption">
<h3>{{ items.itemName }}</h3>
<p>{{ items.description }}</p>
<p>Buy <a href="#" role="button" class="btn btn-default">More Info</a></p>
</div>
</div>
</div>
</div>
"app.js" Angular App
var myApp = angular.module('qcbApp', ['ngRoute', 'ngCookies', 'appControllers']);
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/login', {
templateUrl: 'html/partials/login.html',
controller: 'registrationController'
}).
when('/sign-up', {
templateUrl: 'html/partials/sign-up.html',
controller: 'registrationController'
}).
when('/catalogue', {
templateUrl: 'html/partials/catalogue.html',
controller: 'catalogueController'
}).
when('/', {
templateUrl: 'html/partials/qcbhome.html'
}).
otherwise({
redirectTo: '/'
});
}]);
"catalogueController" Controller
myApp.controller('catalogueController', ['$scope', 'Search', function($scope, Search) {
var time = 0;
var searchCatalogue = function(search) {
$scope.inventory = null;
console.log("Controller -- "+search);
Search.searchCatalogue(search)
.then(function(results) {
console.log(results);
$scope.inventory = results;
});
};
if(time == 0)
{
searchCatalogue('');
time++;
}
$scope.search = function(term) {
searchCatalogue(term);
}
}]);
"Search" Factory
myApp.factory('Search', ['$http', '$q', function($http, $q) {
function searchCatalogue(term) {
var deferred = $q.defer();
console.log("Factory -- "+term);
$http.post('/catalogue_data', {term: term}, {headers: {'Content-Type': 'application/json'}})
.success(function(result) {
console.log(result[0].SKU);
deferred.resolve(result);
console.log("Factory results -- "+result);
});
return deferred.promise;
}
return {
searchCatalogue: searchCatalogue
}; //return
}]);
I think the problem is the ng-repeat can not access the inventory in scope. You have to create a div which contains both the form and the ng-repeat.
The html should be:
<div ng-controller="catalogueController">
<!-- Move the controller from the form to parent div -->
<form role="search" class="navbar-form navbar-left" ng-submit="search(search_term)">
<div class="form-group">
<input type="text" placeholder="Search" class="form-control" ng-model="search_term">
</div>
<button type="submit" class="btn btn-default">Search</button>
</form>
<div id="main" class="margin-top-50 clearfix container">
<div ng-repeat="items in inventory" class="row-fluid">
<div class="col-sm-6 col-md-3">
<div class="thumbnail"><img src="image.jpg" alt="..." class="col-md-12">
<div class="caption">
<h3>{{ items.itemName }}</h3>
<p>{{ items.description }}</p>
<p>Buy <a href="#" role="button" class="btn btn-default">More Info</a></p>
</div>
</div>
</div>
</div>
</div>
I've seen the situation a few times where when you are updating a property directly on the $scope object there are interesting problems around databinding to that value (such as inventory). However if you databind to an object property of an object then the databinding works as expected. So for example use a property on $scope. I believe this is a copy by value vs copy by reference issue.
Update all your inventory references as follows
$scope.data.inventory = result;
Also don't forget to update your inventory reference in the html template:
<div ng-repeat="items in data.inventory" class="row-fluid">
Update: I made this plunk to figure it out - http://plnkr.co/edit/0ZLagR?p=preview
I think the primary problem is you have the controller specified twice. I removed it from the form and it started working.

How to pass parameters to a Modal window in ui-router state

I have been working on an Angular app and I'm stuck on something. I iterate through a list of objects using ng-repeat and have access to this variable ._id. Here's the markup of the parent page: when I delete button gets clicked, I want to pass the ._id to the parent's page (current page) controller so that it could be passed to the Modal window's controller
<tr ng-repeat="bucket in buckets">
<td>{{ bucket.name }}</td>
<td>{{ bucket._id }}</td>
<td class="col-sm-1">
<!-- View Bucket Page -->
<a ui-sref="bucketPage({ bucket_id: bucket._id })" class = "btn btn-primary">View</a>
<!-- Delete Bucket -->
<!-- <a ui-sref="userProfile({ bucket_id: bucket._id })" ng-click="deleteBucketModalWindow('sm')" class="btn btn-danger">Delete</a> -->
<a ng-click="deleteBucketModalWindow('sm')" href="#/" class="btn btn-danger">Delete</a>
</td>
</tr>
I get how to do it when I go to a different page (instead of modal). For that I do this:
<a ui-sref="userProfile({ user_id: user._id })" class = "btn btn-primary">View Profile</a>
Here's the controller of parent page:
// Modal window to delete a Bucket
$scope.deleteBucketModalWindow = function(size){
var user_id = $stateParams.user_id;
var bucket_id = $stateParams.bucket_id;
console.log("bucket id in userProfileCtrl: ", user_id);
console.log("bucket id in userProfileCtrl: ", bucket_id);
var modalInstance = $modal.open({
templateUrl: 'views/deleteBucketModal.html',
controller: 'deleteBucketModalCtrl',
size: size,
bucket_id: bucket_id,
resolve: {
bucket_id: function () {
return $stateParams.bucket_id;
}
}
});
modalInstance.result.then(function(){
// Refresh the data
User.getSingleUserDetails($stateParams.user_id)
.success(function(buckets){
$scope.buckets = buckets;
})
.catch(function(response){
console.log(response);
});
}, function(){
});
};
and here's the controller for the Modal window
angular.module('ResourceBucket')
.controller('deleteBucketModalCtrl', function($scope, $modalInstance, $auth, $http, $window, $rootScope, Bucket){
// Delete the bucket
$scope.deleteBucket = function(){
// close the modal
$modalInstance.close();
console.log("Inside deleteModal - bucket_id: ", $scope.bucket_id);
// bucket_id gets passed through the "resolve"
Bucket.deleteBucket($scope.bucket_id)
.then(function(data){
console.log("Just deleted a bucket!", data);
})
.catch(function(response){
console.log("In catch of deleteBucketModalCtrl: ", response);
});
};
$scope.cancel = function(){
// Just close the modal, dont do anything else
// After you close the modal, in .then() refresh the data
$modalInstance.close();
}
});
and here's the markup for the Modal window
<!-- Add Bucket Modal -->
<div controller="deleteBucketModalCtrl">
<div class="modal-header">
</div>
<div class="modal-body">
<ul>
<!-- Bucket Modal -->
<div class = "row">
<!-- Heading -->
<h2 class="text-center">Sure, you want to delete the bucket?</h2>
<button class="btn btn-danger" ng-click="deleteBucket()">Delete</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</ul>
</div>
<div class="modal-footer">
</div>
</div>
Thank you!
Sorry, actually I figured it out what I was doing wrong. In the markup, you could pass a parameter using ng-click like the following:
<a ng-click="deleteBucketModalWindow('sm', bucket._id)" href="" class="btn btn-danger">Delete</a>

Categories