I am working on a react project. I have made some changes to the way we render content to a screen and am now having a problem finding a solution.
I have a variable that returns text dependent on its content. If the variable is empty, which is its default state, we say that no data was found. If we have some data we render the data. The problem is, that I need to set a default value to the variable so it does not show no data was found when it is analyzing.
I have tried using state to set a analyzed flag but can't seem to get it to work?
So for example:
let filterWhatToShowUser =
// here we filter through the data and determine what the result of filterWhatToShowUser is shown to the user
);
JSX
if there is data ?
<div>Show this</div>
:
<div>Show this when the object is empty</div>
:
<div>Show this whilst the object is empty but evaluating</div>
if(data) => show data
if(!data && ! evaluating) show something
show something else
ternary operator is about "if & else", no need to make complex constructions out of them
so in my angular 5 app i have the following code :
<div *ngFor='let part of (post.student | async).get("qcm")'>
<mat-checkbox>this can't be checked in or checked out</mat-checkbox>
</div>
post.student is of type PromiseObservable.
post.student | async is of type DocumentSnapshot (a Firestore document).
(post.student | async).get("qcm") is an array of three objects.
my problem is :
1) the checkbox is not working (can't be checked in or out)
2) if i try to apply the ngModel directive on the checkbox like so:
<div *ngFor='let part of (post.student | async).get("qcm")'>
<mat-checkbox [(ngModel)]='myBool'>this can't be checked in or checked out</mat-checkbox>
</div>
then the whole site blocks, using task manager i can see that my site have memory leaks now :
task manager
please note that if i use another array of objects other than (post.student | async).get("qcm") everything works fine.
also there are no errors in the console.
i have no idea what's going on, any help is appreciated, thank you!
Since I can't add comments, I just try to post some info that might help you here as an answer.
I don't think you can just add ngModel like that. You have to bind it to an object, like [(ngModel)]="myDataModel". Note that the [] and () are there so there is a two way binding, meaning whatever is in you myDataModel object, will be reflected at the checkbox any time. (So basically - so if you change the model, the cehckbox will change and if you cahnge the checkox the model will change). You dont have to always add two way binding, check the angular site for more information about this.
Also, the checkbox thingy might be a js thingy, check your browser console for errors. I assume some error happened and it interrupted the running of the js code.
I hope it somewhat helps finding your problem.
I am writing a page using Vue.js and am attempting some custom components. I've started with a very simple one:
Vue.component('single-field', {
template: '<b>{{ key }}:</b> {{ value }}',
props: ['key', 'value']
});
This works fine on its own: it is intended to take two values and return them in a key: value format. Initially, when I was passing the value as an element from the Vue data object (specifically, pickup.dateTime it wasn't working. It's easier to show than explain:
<div id="app">
<single-field key="Date & Time" value="pickup.dateTime"></single-field>
</div>
I was able to fix this by binding the value (notice the colon by value):
<single-field key="Date & Time" :value="pickup.dateTime"></single-field>
I then wrote a second component which is designed to take an object and a title and return each element of the object as a set of <single-field> components, with a title above them. Here is what I wrote:
Vue.component('field-block', {
template: '<h2>{{title}}</h2>\
<div v-for="(p-key, p-value) in parent">\
<single-field key="p-key" value="p-value"></single-field>\
</div>',
props: ['parent', 'title']
});
Now, I think there must be something wrong with the way I am binding (or not binding?) which is causing the data to be displayed in a strange way. Here is my HTML:
<div id="app">
<single-field key="DateTime" :value="pickup.dateTime"></single-field>
<single-field key="Name" :value="pickup.name"></single-field>
<field-block title="Address" :parent="pickup.address"></field-block>
</div>
The field pickup.address is an object, so I was hoping that the component would iterate through the elements and return them as single fields, but what it's currently doing is just returning the variable names, like p-key: p-value. I tried doing a bind on both of them in the component definition (on both because they are now both variables being passed whereas previously I was using a static string for the key field):
<div v-for="(p-key, p-value) in parent">
<single-field :key="p-key" :value="p-value"></single-field>
</div>
But what this returns is NaN: NaN, and I can't figure out why it would do that. I don't fully understand the bind operation, but I expect that it only binds to data in the data option when defining the view, which is not where p-key and p-value are defined. How would I get the variables to 'carry through' from the outer component to the inner ones? Thanks.
Okay this one was tricky.
Several problems with your code:
Your components should have only one root element. So pack your components into a <div>.
Then, - is not a valid character to put into a javascript variable name. So you can't write (p-key, p-value) in parent, write something else, like (pKey, pValue) in parent.
On the other hand, html properties are not case-sensitive, so you should actually write key-name (for example) instead of keyName, but only for the property names. This limitation does apply only in your html files (not in your string templates).
Finally, here is a working js-fiddle.
https://jsfiddle.net/6juwLd3b/
Additionally, I would advise you that you look at your console while developing. Many error where displayed that could have lead you to a working version.
So i'm working on a project where players of a game will be able to compare their performance with those of their peers at the same skill level. I can get a prototype of the code to work outside of a durandal structure, but when I try to follow along with other examples while supplying my own sources for the data, I just can't get it all together.
Here is my code:
define(function (require) {
var http = require('plugins/http'),
ko = require('knockout');
var url = 'https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/',
key = '?api_key=#################################';
return {
name: ko.observable,
getSummoner: function() {
var that = this;
if (this.name.length > 0) {
return;
}
return http.jsonp(url + name + key, 'jsoncallback').then(function(response){
that.name(response.items);
});
}
};
});
Replace the #'s with my personal API key that the host recommends I don't share. I'll supply one if necessary and just change it later.
I have 2 specific questions here:
I got the function structure from a tutorial. I don't know why I need to check for length with the IF statement. What is that returning exactly?
This api call returns a JSON object with a nested object inside. What I want, is to display the keys and values from the nested object as li's on the view. Right now I can't even get it to tell me if its actually grabbing the object in the first place.
Here is my HTML:
<section>
<h2>Hello! What user would you like to investigate?</h2>
<form class="form-inline">
<fieldset>
<label>Name</label>
<input type="text" data-bind="value: name, valueUpdate: 'afterkeydown'"/> <!--Text input box-->
<button type="submit" class="btn" data-bind="click: getSummoner, enable: name">Click Me</button><!--This button has both a class and an ID,
Css is linked from index.html-->
<ul data-bind="foreach: name">
<li data-bind="text:$data"></li>
</ul>
</fieldset>
</form>
</section>
What I expect to see is just 1 bullet item that either says object or whatever name is fed into the input box. What I get is nothing.
The returned object (with my username attached) looks like this:
{"ryebrush":{"id":25500750,"name":"RyeBrush","profileIconId":551,"summonerLevel":30,"revisionDate":1426533699000}}
I want to be able to access the ryebrush.id, ryebrush.profileIconId, and so on and so forth. Help?
EDIT: Also, this comes pre-loaded in the input box:
function (b){function c(){if(0<arguments.length)return c.Ka(d,arguments[0])&&(c.P(),d=arguments[0],c.O()),this;a.k.zb(c);return d}var d=b;a.N.call(c);a.a.sa(c,a.m.fn);c.o=function(){return d};c.O=function(){c.notifySubscribers(d)};c.P=function(){c.notifySubscribers(d,"beforeChange")};a.s(c,"peek",c.o);a.s(c,"valueHasMutated",c.O);a.s(c,"valueWillMutate",c.P);return c}
Uhhhhhh.....what?
You sort of asked two questions, so I'm sort of going to give you two and a half answers.
Before we address your first question, you are using the knockout observable function incorrectly, and that is going to cause you lots of headaches. Let's fix that. The following two lines of code will both work similarly. When you call the observable function, you create a new instance of an observable. If you call it with no arguments, the value of the observable is undefined. Since we know you want a string here, it may be preferable to initialize it to the empty string, as in the second example.
name: ko.observable(),
or
name: ko.observable(''),
Then, we can set or retrieve the value of the observable by calling it as a function:
that.name('value');
and
that.name() == 'value';
I got the function structure from a tutorial. I don't know why I need
to check for length with the IF statement. What is that returning
exactly?
After the if statement, you have the following line of code:
http.jsonp(url + name + key, 'jsoncallback')
If name is undefined or empty, you will attempt to make this call to one of two urls respectively:
https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/undefined/?api_key=#
or
https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name//?api_key=#
We know that both should return an error (probably a 400), so there's no point in making those calls. The if statement, when applied to a string, is true when the string is initialized and empty. Note, this will throw an error if the string is undefined, and that's no good.
However, the syntax is also wrong. Technically, the value of that.name is a function and, when treated as a string, will evaluate as
function (b){function c(){if(0<arguments.length)return c.Ka(d,arguments[0])&&(c.P(),d=arguments[0],c.O()),this;a.k.zb(c);return d}var d=b;a.N.call(c);a.a.sa(c,a.m.fn);c.o=function(){return d};c.O=function(){c.notifySubscribers(d)};c.P=function(){c.notifySubscribers(d,"beforeChange")};a.s(c,"peek",c.o);a.s(c,"valueHasMutated",c.O);a.s(c,"valueWillMutate",c.P);return c}
Recall from above, a much better thing to write in the if statement is
if (!that.name())
We call the function to get the value. Both '' and undefined are falsey in javascript, and so the if statement will catch both cases and exit, which is what we want. Note it will also exit if the value of name is 0, or any other falsey javascript value.
This api call returns a JSON object with a nested object inside. What
I want, is to display the keys and values from the nested object as
li's on the view. Right now I can't even get it to tell me if its
actually grabbing the object in the first place.
There are a number of things wrong with your view.
<ul data-bind="foreach: name">
This will iterate through the value of that.name. If that.name is 'ryebrush', this will (I believe), iterate through each letter. That's no good. If your goal is to have a list of summoners in that.name, you will want to swap ko.observable with ko.observableArray. You may also want to change the name that.name to that.names to avoid confusion.
<li data-bind="text:$data"></li>
This is right if your array is filled with strings. foreach will iterate through each item in the array, and $data is each item. However, if the item is in fact an object, you can reference properties on the item. For example, if each item in your array is
{"id":25500750,"name":"RyeBrush","profileIconId":551,"summonerLevel":30,"revisionDate":1426533699000}
then, since name is a property on the object, you can reference name in your view
<li data-bind="text:name"></li>
Finally, you're not actually getting the data in the right place after your http call. If the response to your http call is
{"ryebrush":{"id":25500750,"name":"RyeBrush","profileIconId":551,"summonerLevel":30,"revisionDate":1426533699000}}
Then you would want to write
return http.jsonp(url + name + key, 'jsoncallback')
.then(function(response){
that.name(response["ryebrush"]);
});
If the response is instead an array of items
[{"ryebrush":{"id":25500750,"name":"RyeBrush","profileIconId":551,"summonerLevel":30,"revisionDate":1426533699000}}]
Then you would want to write
return http.jsonp(url + name + key, 'jsoncallback')
.then(function(response){
that.name(response[0]["ryebrush"]);
});
Conclusion
Unfortunately, this isn't a great question. I can't tell exactly what's going on with the API you're using, so I can't tell you exactly what you should write. To accomplish what you're trying to do, you'll need to spend a little bit of time reading up on javascript, knockout, and durandal. Here are some good resources for each:
javascript
knockout
durandal
However, I see you're a new user. I want to encourage you not to get discouraged. It'll take a bit of time to to learn the ropes, but it's worth it. Don't give up. I hope this helps!
I'm actually not sure how to ask this question, and I'm probably using incorrect terms, so bear with me.
Angular sets up a 2-way data binding so that it makes it easy to work with the data on both sides. But what if I want to change how that data is represented?
Let me give a concrete example.
I want a form with a checkbox, which if bound directly to a model, would be stored as true or false by Angular. However, in another part of the webpage I want that value to show up as 0 or 1, not true or false.
Now sure I could go and make them use two different variables, and use ng-change or something like that to update one based on the other, but that seems overkill and convoluted.
Is there some special meta function or something I can define that lets me essentially translate the data as it goes back and forth?
Use the ngTrueValue and ngFalseValue directives. They define what should be treated as true and false on a checkbox: https://docs.angularjs.org/api/ng/input/input%5Bcheckbox%5D
Example:
<input type="checkbox" ng-model="foo"
ng-true-value="OK"
ng-false-value="BOO-HOO">
The model will either have a value of "OK" or "BOO-HOO" instead of the default true and false in the above example.
Alternatively, if you want the original model to retain its default values and only draw the custom ones from another variable, you could also use the ngChange directive:
<input type="checkbox" ng-model="foo"
ng-change="bar=foo&&'OK'||'BOO-HOO'">
Now, whenever foo changes, bar will have the corresponding alternative value. Just remember to assign bar an initial value (it will start out with no value at all).
in your controller...
$scope.getvalue(data)
{
if(data===true)
return 1; // write what ever you want...
return 0;
}
in your html page..
bind the normal one as {{$scope.data1}} and other as {{getvalue($scope.data1)}}
You can do some nice things with ngBind:
Check this plunker: http://plnkr.co/edit/cRhLN2p5N4PmI65ps6Gp?p=preview
<input type="checkbox" ng-model="ok"> OK?
<h2>true or false: {{ ok }}</h2>
<h2>0 or 1: {{ ok ? 1 : 0 }}</h2>