angular.js passing function into an object - function

I think it may be useful if I show the wider scope :) below is my html:
<div class="resSection2 rel">
<div class="proceed rel">
<div ng-repeat="record in records">
<div class="rel fptsans {{record.className()}}">Balkans<i class="icon-check icon-2x posIco"></i></div>
</div>
</div>
</div>
Key factor here is the {{record.className()}} binding which depending on its value determines the behaviour of the record, whether it gets a proper styling or not. as you can see it is a reference to a function. And here is the JS:
var antroApp = angular.module('antroApp', []);
$scope.records = [
{id:0,
className: $scope.probieren,
recordName:$scope.alpeic.length
},
{id:1,
className: $scope.probieren,
recordName:$scope.alpeic.length
}
];
$scope.probieren = function(){
if($scope.records.recordName > 10){
$scope.records.className == 'special'
}
else{
$scope.records.className == 'normal'
}
}
}
antroApp.controller('dialogWindows', dialogWindows);
When I set up the className statically ("special" or "normal") it renders perfectly
but when it comes to a function, it all just gets stuck. really feel helpless about this. any tips appreciated.

You've set it up fine except they have to be defined in the other order, but in your dom when you use it call a function like this:
<div data-ng-repeat="record in records">
<div class="{{ record.className() }}">{{ record.recordName }}</div>
</div>
There's a few more issues with how you're referencing $scope.records.className instead of some index of the array for records but my answer should answer the specific question you have.

Related

Array of calendars with ViewChildren?

I need to create a dynamic full-calendar array.
The idea is that the user can select one of "n" diaries, relating to different operators, which are shown to him at the same time.
I'm using Angular 9.
Of course... it doesn't seem to work...
My .ts file has this declaration...
#ViewChildren(FullCalendarComponent) fullCalendars: FullCalendarComponent[];
public calendarOptions: CalendarOptions = null;
...and I use the component in this way...
render() {
if (this.fullCalendars && this.fullCalendars.length > 0) {
this.fullCalendars.forEach(fc => fc.getApi().render());
}
}
... and this is the HTML part ...
<div class="card" *ngFor="let ag of agendas; let i = index">
<div class="card-header">
<b>{{ ag.description }}</b>
</div>
<div class="card-body">
<full-calendar #fullCalendars [options]="calendarOptions"> </full-calendar>
</div>
</div>
Is this correct? I'm trying to understand why I'm getting this error...
Cannot read properties of undefined (reading '0')
...but first I need to know if the above code is ok.
Thank you so much!

What is the proper way to show different elements based on function return

So basically what I want is to show
'Something1' when the job is not processing
'Something2' when the job is running and status is '0'
'Something3' when the job is running but status is something else
I tried the following code snippet, but it looks like let-status in the outer template will never get assigned. Not sure whether the implementation is correct or not, could anyone give me two cents on how to make this logic work?
Thanks.
<span *ngIf="!isProcessing(); else elseBlock">
Something1
</span>
<ng-template #elseBlock let-status="queryPlaybackStatus()" *ngIf="queryStatus() === '0'; else innerElseBlock">
<span>
Something2
</span>
<ng-template #innerElseBlock>
<span>
Something3
</span>
</ng-template>
</ng-template>
I would suggest defining a string in your component, where you have much better control over your logic. In the component, set the string to the appropriate text.
Then bind to that string in the template.
I don't have all of your needed logic here, but something like this:
isImage = false;
get statusText(): string {
if (!isProcessing()) {
this.isImage = false;
return 'Something1';
} else {
this.isImage = true;
return 'path to image';
}
}
This uses a getter, which provides a way for a component property to have logic.
Then just bind to statusText in the template.
<span *ngIf='!isImage'>
{{statusText}}
</span>
<span *ngIf='isImage>
<img ...>
</span>
<span *ngIf="!isProcessing(); else elseBlock">
Something1
</span>
<ng-container #elseBlock *ngIf="queryStatus() as status">
<span *ngIf="status === '0'; else innerElseBlock">
Something2
</span>
<ng-template #innerElseBlock>
<span>
Something3_with_{{status}}%
</span>
</ng-template>
</ng-container>
So basically this need a magic combination of ng-container and ng-template.
It sounds to me like you want ngSwitch. This allows you to switch based on logic, which you should encapsulate in your component, not your template. First, let's create a property that encapsulates our logic in our component:
public get currentStep(): number {
if (!this.isProcessing) {
return 1;
} else if (this.queryStatus === 0) {
return 2;
} else {
return 3;
}
}
Next, let's bind our ngSwitch statement to this newly-created property:
<div [ngSwitch]="currentStep">
<div *ngSwitchCase="1">
<p>Something1</p>
<div>Put whatever you want in here! Images, etc.</div>
</div>
<div *ngSwitchCase="2">
<p>Something2</p>
<p>Loading....</p>
</div>
<div *ngSwitchCase="3">
<p>Something3</p>
<p>All done!</p>
</div>
</div>
That should get you where you need to go. Since this is simple, I created a stackblitz example that will demonstrate a working version of this. In the example, you can click a button and watch the app cycle through all the steps (I'm using setTimeout to simulate a long-running server query).

access certain element of JSON in angular JS

Below is my JSON file:
[
{
"Name":"Peter England Shirt",
"Prodimage":["./images/zoom/zoom1hi.jpg","./images/zoom/zoom2hi.jpg","./images/zoom/zoom3hi.jpg"],
"actualPrice":"90",
"discountedPrice":"70",
"desc":"Cotton",
"Prodcolor":["#f1f40e","#adadad","#4EC67F"],
"quantity":[1,3,4,5,60],
"size":["XL","L","M","S"],
"detail":"Take it away",
"sizeChart":["16 waist","Measurements taken from size 30","Model wears size 31. Model is 6'2"],
"shipping":[
{
"type":"Standard",
"days":"5-6 days",
"cost":"200"
},{
"type":"Next day",
"days":"1 days",
"cost":"500"
}
],
"sellerList":[
{
"sellerName":"ABC",
"price":"566",
"deliveryDay":"4-5 working days"
},{
"sellerName":"SEDF",
"price":"300",
"deliveryDay":"4-5 working days"
},{
"sellerName":"QWER",
"price":"555",
"deliveryDay":"2-5 working days"
}
]
}
]
The JS file is as below:
var pJson="./json/product.json";
$http.get(pJson).success(function(response){
$scope.product=response;});
Now, if I want to access "Name" attribute I can call {{product[0].Name}}.
But I am not able to access Prodimage attribute using ng-repeat. I am trying like this:
<div ng-repeat="image in product.Prodimage">
{{image[0]}}
</div>
is this wrong?>
Yes this is wrong ,, note that you have the product object as array ,, so if you want the first object you should do this
<div ng-repeat="image in product[0].Prodimage">
{{image[0]}}
</div>
or if you want to iterate over all the products ,, you need to make a nested ng-repeat
<div ng-repeat="p in product">
<div ng-repeat="image in p.Prodimage">
{{image[0]}}
</div>
</div>
You could loop over it, becasue the outside is technically an array, and use $first for you example of wanting to only grab the first image. You could also use $index but running it through a function that checks the $index.
Fiddle here http://jsfiddle.net/HB7LU/15324/
I just re worked it to loop twice like so
<div ng-repeat="prod in product">
<div ng-repeat="image in prod.Prodimage">
<div ng-show="$first">
{{image}}
</div>
</div>
</div>
then put a div inside the inner repeat that will only show if it's the first item. Again you could change that logic to show by index, or whatever you want. So if you know the index you could change that same logic to this -
see fiddle - http://jsfiddle.net/HB7LU/15332/
<div ng-show="checkIndex($index)"> << or whatever index you want
{{image}}
</div>
and in the controller
$scope.checkIndex = function(item){
if(item === 0){
return true;
}else{
return false;
}
}
You just pass the index of the current item in the repeat and check it. I would recommend this logic over the Prodimage[0] logic so you are not hardcoding it into the html, so if you have to change the desired index, you change it in the controller, not template. The checkIndex is a quick example, you could change that to do whatever you want.
$scope.product[n].Prodimage is an array. So, you need to loop through your product array first, and then loop through the Prodimage array of each product:
<div ng-repeat="prod in product">
<div ng-repeat="image in prod.Prodimage">
{{ image }}
</div>
</div>
Of course, you could also just access the nth image using something like:
<div ng-repeat="prod in product">
{{ prod.Prodimage[0] }}
</div>
Can you change your json to
"Prodimage":[
{ "loc": "./images/zoom/zoom1hi.jpg"},
{ "loc": "./images/zoom/zoom2hi.jpg"},
{ "loc": "./images/zoom/zoom3hi.jpg"}],
then your loop should work
<div ng-repeat="image in product.Prodimage">
{{image.loc}}
</div>

Angularjs load json into a specific div

I'm new to AngularJS but I love the framework.
What I have right now, is a (stub) single page that loads json data.
JS
var merlinoApp = angular.module('merlino', []);
merlinoApp.controller('mainController', function ($scope, $http) {
...
$http.get('#Url.Action( "consoledatapull", "ConsoleElaborazioni")')
.then(function (res) {
$scope.jobs = res.data.jsonjobs;
$scope.clienti = res.data.jsonclienti;
$scope.console = res.data.jsonconsole;
});
...
});
HTML
<div ng-repeat="roll in jobs | orderBy:sortType:sortReverse | filter:searchJob | filter:searchCliente | filter:searchStato" class="console-row my-row">
...
<div class="console-cell-id console-cell console-cell-padding console-cell-no-border-sx">{{ roll.id }}</div>
...
<div ng-click="collapsed=!collapsed" ng-class="{'console-cell-esito-selected' : collapsed}" class="console-cell-esito console-cell console-cell-no-border-sx">SHORT DESC</div>
<div ng-show="collapsed" class="console-cell-esito-long console-cell console-cell-no-border-sx">{{ roll.esito }}</divng-show></div>
</div>
This populates ng-repeat, and the ng-click shows/hides the `ng-show div.
So far so good(?).
What Ì'm trying to achieve, is to load json data into
<div ng-show="collapsed" class="console-cell-esito-long...
if
<div ng-click="collapsed=!collapsed" ng-class="{'console-cell...
is clicked.
That is each div of ng-repeat, can be loaded with specific data:
<ul>
<li ng-repeat="logelem in jsonlog">
{{ logelem.log }}
</li>
</ul>
I thought about using a function:
<div ng-click="function(id)...
and then load json into a div identified by an id, so i used $index...
The result was, being able to load same data into all divs at once :/
Help would be appreciated.
My suggestion woudl be to add the information to the jobs elements itself.
So for example, the ng-click would become:
<div ng-click="loadData(id, roll)">CLICK ME</div>
and then the loadData would be something like:
$scope.loadData = function(id, roll){
// Do something
roll.result = result;
}
and then you can use the result from that object in the view like you would do in other places. You can then for example hide the object where you want the final result until the variable result is defined.
I think this will be the easiest solution.
Update from comments
Why not change the collapsed value in the method? Or you could use a $watch to listen to changes on the collapsed variable.

Load view after data is loaded

I have some trouble. I am using this plugin "angular-masonry" (it's on Github) to dynamically build the grid on the page. When the page loads I get this:
http://joxi.ru/YBQPVP3JTJCwfIgLgbc
Here is my code:
<div class="container" style="width:80%">
<h1 style="text-align: center; margin-bottom: 40px">
Category: {{category.text}}
</h1>
<div>(masonry='' load-images="false")
<div class="masonry-brick" ng-repeat="portal in category.claim_portals" style='width:50%;float:left'>
<div>
<h3>(style='margin-left:30px')
Portal: {{portal.text}}
</h3>
<div class="category-list" ng-repeat="claim in portal.portal_claim" style="margin-bottom:2px">
<div class="claim_sections">
<claimforlist claim="claim"></claimforlist>
</div>
</div>
</div>
</div>
</div>
</div>
But after resizing browser window, everything becomes normal and looks like this:
http://joxi.ru/iBQPVP3JTJCUfLnoqQQ
I think that view loads earlier than JSON data arrives.
Can anyone help and tell me how can I load view after the data has arrived? Or if you know another reason of such an issue, please reply.
Thanks in advance.
You can add a scope boolean variable with value set to false, and change the value to true on your http promise success.
Code sample:
function myController($scope, YourDataServer) {
$scope.dataLoadedSuccessfully = false;
yourDataServer
.query()
.$promise
.then(
function(result) {
$scope.dataLoaded = true; // set the value to true
});
}
HTML would look like:
<div id="loadingBar" ng-show="!dataLoadedSuccessfully">Loading data...</div>
<div id="dataWrapper" ng-show="dataLoadedSuccessfully">
<!-- data goes here -->
</div>