AngularJS - Cannot set scope value into template - javascript

I have following function:
$scope.setDetailToScope = function(data) {
$scope.$apply(function() {
//$scope.order = data;
$rootScope.order = data;
setTimeout(function() {
$scope.$apply(function() {
//wrapped this within $apply
$scope.order = data[0];
console.log('message:' + $scope.order);
console.log($scope.order);
});
}, 100);
});
};
"
console.log($scope.order);
Gives me values which has been set into scope.
But i cannot get these values in template.
<!-- DEBUG DIV -->
<div class="debugDiv" ng-show="$root.debugable == true">
{{columns}}
</div>
<div data-ng-controller="OrdersCtrl" ng-init="initData()">
<div id="orders_grid" >
</div>
</div>
<!-- GRID TOOLBAR BUTTON TEMPLATE -->
<script id="template" type="text/x-kendo-template">
<a class="k-button" href="\#/orders/create">Add</a>
</script>
<!-- ORDER DETAIL DIV -->
<div class="container" id="orderDetail" data-ng-controller="OrdersCtrl" ng-if="'detailSelected == true'" xmlns="http://www.w3.org/1999/html">
<!-- DEBUG DIV -->
<div class="debugDiv" ng-show="$root.debugable == true">
{{order}} <!--NOT WORKING-->
</div>
If i tried to add values into rootscope it works, but in this case i cannot get value into ng-model.
What i'm doing wrong please?
Many Thanks for any help.
EDIT:
If i tried solution wit $timeout i got on console.log($scope.order);
following object which is not passed into the template:
_events: ObjectacrCrCode: "interlos"actionName: ht.extend.initarchived: falsebaseStationInfo: ht.extend.initbsc: "bsc1"btsRolloutPlan: "plan1"candidate: "B"costCategory: ht.extend.initcreatedBy: ht.extend.initdirty: falsefacility: ht.extend.initid: 3location: ht.extend.initmilestoneSequence: undefinednetworkType: "Fix"note: "poznamka"orderNumber: 111113orderType: ht.extend.initotherInfo: ht.extend.initparent: function (){return e.apply(n||this,r.concat(h.call(arguments)))}partner: ht.extend.initpersonalInfo: ht.extend.initproject: ht.extend.initpsidCode: "psid1"sapSacIrnCode: "sap1"uid: "924c0278-88d0-4255-b8ac-b004155463fa"warehouseInfo: ht.extend.init__proto__: i

well I'm not sure why you are using a setTimeout with scope apply, to me is safer to use a $timeout since it fires another digest cycle,
try something like
$scope.setDetailToScope = function(data) {
$timeout(funtion(){
//$rootScope.order = data; try either data or data[0]
$scope.order = data[0];
},100);
};
please note that calling nested apply methods can run into some problems with the angularjs digest cycle you may get an error like "digest already in progress" so put attention to it.
NOTE:
it seems like you got some dirty data there, so try to do a map between the data and the scope
$scope.order ={};
$scope.order.uid = data.uid;
$scope.order.orderNumber = data.orderNumber //and so on
in your template try something like:
<div class="debugDiv">
<p> {{order.uid}} </p>
<p> {{ order.orderNumber}} </p>
</div>
this could be a little bit rustic but it worth to try it out.

Related

How to use injected constants in html file in AngularJS

I have a constant file which looks like this
demo.constant.js
// Add detail constans here
(function () {
angular.module('myApp').constant('TYPE', {
DYNAMIC: 'dynamic',
STATIC: 'static'
});
}());
Now I have a controller file that looks similar to this.
demo.controller.js
(function() {
var DemoController = function(DEP1,DEP2, .... , TYPE)
console.log(TYPE.DYNAMIC); // works perfectly
var self = this;
self.type = '';
...
...
angular.module('myApp.controllers').controller('DemoController', DemoController);
})();
I am trying to access these constants in the HTML file like this:-
<div ng-controller="DemoController as self">
<span ng-if="(self.type === 'dynamic')"> <!--instead of 'dynamic' I want to use TYPE.DYNAMIC-->
...
...
...
</span>
</div>
Note:- {{self.type}} works but {{TYPE.DYNAMIC}} doesn't.
Another problem is that I want to use this constant as the value of radio buttons.
somewhat like this:-
<input type="radio" name="type" ng-model="self.inputType" value="dynamic"> <!-- Here I want to use TYPE.DYNAMIC -->
<input type="radio" name="type" ng-model="self.inputType" value="static"> <!-- Same as above -->
I have searched everywhere but nothing seems to work. Please Help!!
One approach is to assign the constant to a controller property:
function DemoController(DEP1,DEP2, /*.... ,*/ TYPE) {
console.log(TYPE.DYNAMIC); // works perfectly
this.TYPE = TYPE;
}
angular.module('myApp.controllers').controller('DemoController', DemoController)
Then use it in the template:
<div ng-controller="DemoController as $ctrl">
<span ng-if="$ctrl.type === $ctrl.TYPE.DYNAMIC">
...
</span>
</div>
Note: The ng-if directive uses creates a child scope. Consider instead using the ng-show directive which uses CSS and less resources.
You can use $rootScope and initilize it in run phase:
angular.module('app')
.run(function ($rootScope, TYPE) {
$rootScope.TYPE = TYPE
});
then you can use it directly in your HTML

If HTML response is null, display alternate content

My api call returns html, but if that html is empty e.g. I get a console html response of "", I want to display a default message using knockout. So I'm guessing that it needs to recognise that "" is empty and then display my alternate content.
View model -
var MyText = ko.observable();
var company = shell.authenticatedCompany();
hazibo.helpTextGet(company.name, company.userName, company.password).then(function (data) {
MyText(data);
});
return {
MyText: MyText
};
View -
<section class="help-text">
<div class="flex-container">
<div class="flex-item" data-bind="html: MyText">This is my alternate message if the html response is ""</div>
</div>
</section>
There are a few ways you could go about it. Personally I like to keep as much code out of the markup as possible so I would check your response data in the api callback and set it there. No need to create messy looking data bindings if you just update the observable appropriately.
hazibo.helpTextGet(company.name, company.userName, company.password).then(function (data) {
if(!data) {
MyText("This is my alternate message...");
}else{
MyText(data);
}
});
If you need to preserve what the api call actually returned you could place the logic in a computed instead, and bind to that.
One way to achieve this is to use a computed observable to determine which set of html to display:
https://jsfiddle.net/dw1284/ucnewzwo/
HTML:
<section class="help-text">
<div class="flex-container">
<div class="flex-item" data-bind="html: ItemHtml()"></div>
</div>
</section>
JavaScript:
function ViewModel() {
var self = this;
// Html populated from API call
self.MyText = ko.observable('');
// Default Html
self.Default = ko.observable('This is my alternate message if the html response is ""');
// Computed observable chooses which HTML to display (bind this to view)
self.ItemHtml = ko.computed(function() {
if (!self.MyText() || self.MyText() === '') {
return self.Default();
} else {
return self.MyText();
}
});
}
ko.applyBindings(new ViewModel());

Angular JS === comparison not working

I am trying to compare the value passed from the url to a controller to a field in a json file.
galleryItem.html
<div class="filter-box">
<ul class="filter list-inline text-center" ng-repeat="gal in ParentData">
<li></li>
</ul>
</div>
<div class="container-fluid">
<div class="row">
<div class="portfolio-box" ng-repeat="x in data">
<div class="col-sm-4">
<div class="item-img-wrap">
<img ng-src={{x.url}} class="img-responsive" alt="">
<div class="item-img-overlay">
<a href={{x.url}} class="show-image">
<span></span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
The updated controller:
controllers.controller('GalleryViewCtrl', function GalleryViewCtrl($scope, $http, $stateParams) {
$scope.pageName = '';
$scope.Description = '';
$scope.GalleryID = $stateParams.id;
$http.get('/data/galleryItems.json')
.then(function (response) { $scope.ParentData = response.data.galleries });
$http.get('/data/galleryItemImages.json')
.then(function (response) {
$scope.data = response.data.images.galleryIdentifier === $stateParams.id;
});
});
I verified the correct value is being passed in to the controller, the values are static and so is the data being passed from the json file. I placed an if statement to check for null as suggested as well. I removed it temporarily to reduce what I'm working with.
If I remove the === $stateParams.id i get all of the images returned and displayed correctly.
If I replace $stateParams.id with a value that I know is in the list (4 or '4') i do not get anything returned. I also tried the value for the last item in the list.
There are no errors (loading scripts, reading json etc.) and all of the values are correct when I'm debugging.
I am still new to this and there is so much documentation with different solutions it all gets very confusing. If anyone has any ideas they would be greatly appreciated.
You are loading data to the $scope.data when the ajax call returns some data. I am assuming your view code is calling the galleryFiltered even before that. May be try to add a null check before returning the value from the method.
$scope.galleryFiltered = function () {
if($scope.data!=null)
{
return $scope.data.galleryIdentifier === $scope.GalleryID;
}
return false;
};
Remember that $http service returns a promise so your $scope.data will be undefined (or holding current state) until $http.get('/data/galleryItemImages.json') will return a success callback function and assign new value to $scope.data from response.
If you'll run $scope.galleryFiltered() before promise gets resolved you will have $scope.data == undefined or whatever data is stored on $scope.data at the time or $scope.galleryFiltered() execution.

binding to controller object in Angular

I'm new to angular, trying to bind an an element's content into the controller's Scope to be able to use it within another function:
here is the scenario am working around:
I want the content of the <span> element {{y.facetName}} in
<span ng-model="columnFacetname">{{y.facetName}}</span>
to be sent to the controller an be put in the object $scope.columnFacetname in the controller
Here is a snippet of what I'm working on:
<div ng-repeat="y in x.facetArr|limitTo: limit track by $index ">
<div class="list_items panel-body ">
<button class="ButtonforAccordion" ng-click="ListClicktnColumnFilterfunc(); onServerSideButtonItemsRequested(ListClicktnColumnFilter, myOrderBy)">
<span>{{$index+1}}</span>
<span ng-model="columnFacetname">{{y.facetName}}</span>
<span>{{y.facetValue}}</span>
</button>
</div>
</div>
angular.module('mainModule').controller('MainCtrl', function($scope, $http) {
$scope.columnFacetname = "";
$scope.ListClicktnColumnFilter = "";
$scope.ListClicktnColumnFilterfunc = function() {
$scope.ListClicktnColumnFilter = "\":\'" + $scope.columnFacetname + "\'";
};
}
the problem is that the $scope.ListClicktnColumnFilter doesn't show the $scope.columnFacetname within it, meaning that the $scope.columnFacetname is not well-binded.
In your ng-click instead of calling two different function
ng-click="ListClicktnColumnFilterfunc(); onServerSideButtonItemsRequested(ListClicktnColumnFilter, myOrderBy)"
you can declare like this
ng-click="columnFacetname = y.facetName; onServerSideButtonItemsRequested(columnFacetname , myOrderBy)"
You are trying to pass that model to another function by assigning it to ListClicktnColumnFilter in your controller
By doing in this way, you can achieve the same thing.
I have done one plunker with sample array,
http://embed.plnkr.co/YIwRLWXEOeK8NmYmT6VK/preview
Hope this helps!

Set value in HTML with AngularJS

I'm using Angular JS. I loop out a part of a scope that from the start is a JSON array.
I need to check for if a value in that array exists. If it does it should do something. The following code work but I can't figure out a way to save "status" temporary.
<div ng-repeat="item_value in item['slug'].values">
{{item_value}}
<div ng-if="item_value == 'dogs_cats'">
Somehow save "status" to true when above is equal.
</div>
</div>
<div ng-if="status == 'true'">
Do someting here.
</div>
Maybe my approach is wrong. Maybe this should not go in the template? I like different solutions to choose from and suggestions on which would be prefered.
I think something like this would do:
<div ng-if="item_value == 'dogs_cats'" ng-init="status = true">
Somehow save "status" to true when above is equal.
</div>
But preferably you should put that logic in controller
You should refactor some of this into a controller. Try something like:
HTML:
<div ng-controller='itemSlugs'>
<div ng-repeat="item_value in item['slug'].values">
{{item_value}}
</div>
<div ng-if="status">
Do something here.
</div>
</div>
Javascript:
angular.module('myApp', []).
controller('itemSlugs', ['$scope', function($scope){
$scope.item.slug.values = [ /*initialize here*/ ];
$scope.status = false;
$scope.$watch('item.slug.values', function(){
$scope.status = false;
$scope.item.slug.values.forEach(function(item_value){
if (item_value == 'dogs_cats'){
$scope.status = true;
}
});
});
});
I added a watch so if any values in your item.slug.values changes, then the status will update accordingly.

Categories

Resources