Trouble outputting model data dynamically with jQuery - javascript

I am trying to create some divs out of my view model using jQuery. This is the code:
<script src="~/Scripts/jquery-3.1.1.min.js"></script>
<script>
$(document).ready(function () {
var model = #Html.Raw(Json.Encode(Model.MemberProfiles));
console.log(model);
for (profile in model) {
$("#viewMembers").append("<div class='profilePreview'><p>" + profile["FirstName"] + "</p></div>");
}
$("#viewMembersBtn").click(function () {
$("#viewMembers").toggle();
});
});
As you can see here, the "FirstName" property evaluates to undefined. If you look at the console.log() in this same image, the objects have the correct data. How do I retrieve the FirstName property correctly?

You need model[profile].FirstName:
for (var profile in model) {
$("#viewMembers").append("<div class='profilePreview'><p>" + model[profile].FirstName + "</p></div>");
}

Try to access your JavaScript Model like this:
for (profile in model) {
$("#viewMembers").append("<div class='profilePreview'><p>" + profile.FirstName + "</p></div>");
}

Related

Make a query with JSON

I have JSON data gets Vedios data of youtube list. And the following link display structure of my JSON.
<a href="https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=UUbW18JZRgko_mOGm5er8Yzg&key=AIzaSyDGm1uzuqPPUGzG-qN7u6gTaS8ApXBJYvw">
Click me to get all list videos ID ...
</a>
And here is the channel with its ID
After analyses of my JASON, I have JSON array named "items" (row 9).
Now all I need to get specific information from all units included with this array "items".
All I need to make a query using JavaScript or c# to return JSON with this specific data
title
description
thumbnails - standard
videoId
Finally, I found a solution for my problem. Not very professional but good for now.
I used Jquery selectors to extract data from my JSON object as following.
$(document).ready(function () {
var jsonLink = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=PL0zTBP9-UnPaIurxKLr3rfPZwHrFl2mEq&key=AIzaSyDGm1uzuqPPUGzG-qN7u6gTaS8ApXBJYvw&maxResults=50";
$.getJSON(jsonLink).done(function (data) {
var items = [];
$.each(data.items, function (i, item) {
items.push("<li>" + item.snippet.title + "</li>");
if (i === 5) {
return false;
}
});
$("<ul/>", {
"class": "my-new-list",
html: items.join("")
}).appendTo("body");
});
});

How to provide dynamic className to element in React Class render method

I have a ReactClass with name Alert. Its render method returns a div with class alert alert-success or alert alert-error according to the type passed while creating element. I just want to know how to add class based on the type of alert element.
Here is my attempt:
var Alert = ReactClass({
render: function() {
return <div className="alert {this.props.type}">{this.props.message}</div>
}
});
var successAlert = React.createElement(Alert, {
type: 'alert-success'
message: 'Information saved successfully!!'
});
When JSX Template is compiled this.props.type is not converted to the class passed to element. How to achieve this ?
Looks like I have found answer to my question. We can simply do something like this:
var Alert = ReactClass({
render: function() {
return <div className={"alert " + this.props.type}>{this.props.message}</div>
}
});
Just put your classes inside Template evaluators { } in this case. Create your class string based on your props and states.
Hope this is helpful to others.
One way to accomplish this is to have a string which will contain all of your classes and then set it to the Component's className:
var Alert = ReactClass({
var yourClassName = 'alert ';
// Add any additional class names
yourClassName += this.props.type + ' ';
render: function() {
return <div className={yourClassName}>{this.props.message}</div>
}
});
or alternatively you can store your class names in an array and convert it to a class friendly string when you're ready to use it:
var Alert = ReactClass({
var yourClassArray = [];
// Add any additional class names
yourClassArray.push('alert');
yourClassArray.push(this.props.type);
var classString = yourClassArray.join(' ');
render: function() {
return <div className={classString}>{this.props.message}</div>
}
});
Take a look at the classnames package. You can do stuff like this:
className={classNames('alert', `alert-${type}`)}
or
className={classNames({
'alert': true,
'alert-success': success,
'alert-error': error
})
You can use JavaScript template literals
var Alert = ReactClass({
render: function() {
return <div className={`alert ${this.props.type}`}>{this.props.message}</div>
}
});
Your code can be written in following way:
const Alert = ({type, message}) =>
<div className={`alert ${type}`}>{message}</div>
Write in code
className={`form-control-sm d-inline per_player ${"per_player_b_" + index + "_score"}`}
and You will get

Alter the template from the `createViewModel` function within a custom component loader

In knockoutjs I have a custom component loader in which I do some logic. Basically I want to alter the template from the createViewModel function. I know there's the componentInfo.templateNodes but I don't know what to do with it.
The reason I want to alter it in the createViewModel function is because the createViewModel function is called every time a component is shown.
Ahwell, code says way more than words so check it out yourself down here.
ko.components.loaders.unshift({
getConfig: function (name, callback) {
var component; // The component gets loaded somewhere. (Sadly I can't alter the template here because it is only called once.)
callback({
viewModel: {
createViewModel: function (params, componentInfo) {
// Load these parameters somewhere
var args;
var location;
// I'd love to add these two items before and after my template.
var before = "<div data-bind=\"with: " + location + "\">";
var after = "</div>";
// Construct a viewModel with the data provided.
return app.core.helpers.construct(component.viewModel, location, args);
}
},
template: component.template
});
},
loadTemplate: function (name, template, callback) {
// Get the location again.
var location;
// I just want to load the template while applying the correct binding scope from the createViewModel.
var templateString = "<!-- ko stopBinding: true -->\n<!-- ko with: " + location + " -->\n" + template + "\n<!-- /ko -->\n<!-- /ko -->";
// Just let it load.
ko.components.defaultLoader.loadTemplate(name, templateString, callback);
}
});
I managed to create a working solution (although in its infancy). As I still don't know how to add template code to the componentInfo I discovered it is possible to edit the things available in the componentInfo. (See the solution below)
ko.components.loaders.unshift({
getConfig: function (name, callback) {
var component;
callback({
viewModel: {
createViewModel: function (params, componentInfo) {
// Load these parameters somewhere
var args;
var location;
/*
* The first one is the element we're binding on. The next sibling is the element we probably want to alter.
*/
if (componentInfo.element.nextSibling.nodeType == 8 && componentInfo.element.nextSibling.nodeValue.indexOf("[injectNamespace]") > -1) {
componentInfo.element.nextSibling.nodeValue = "ko with: models." + name.replace('/', '.');
}
return app.core.helpers.construct(component.viewModel, location, args);
}
},
template: component.template
});
},
loadTemplate: function (name, template, callback) {
var templateString = "<!-- ko with: [injectNamespace] -->\n" + template + "\n<!-- /ko -->";
ko.components.defaultLoader.loadTemplate(name, templateString, callback);
}
});

Writing helper : What's the use of the end arguments

Apologies for the name of the question, you will quickly understand what I mean.
On Ember website, if you follow the example given you will get the following :
Ember.Handlebars.helper('fullName', function(person) {
return person.get('firstName') + ' ' + person.get('lastName');
}, 'firstName', 'lastName');
But if you take out the end of the function it's still working :
Ember.Handlebars.helper('fullName', function(person) {
return person.get('firstName') + ' ' + person.get('lastName');
});
Is there any advantage, disadvantage to add/remove these values.
The first aproach have dependent keys, so if firstName or lastName is changed, the template is updated. The second just observe the person instance, not your properties.
Give a look in that fiddle for further understanding
These values indicate the properties to which this helper is bound to. This means that if the values of these properties change the helper will be updated.
The following example demonstrates this ,
http://emberjs.jsbin.com/udOkupe/1
By pressing the test button the firstName value is changed, only one of the fullName helpers will be updated.
hb
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
{{firstName}}<br/>
{{lastName}}
<br/>
{{fullName this.model}}<br/>
{{fullName2 this.model}}<br/>
<button {{action "test"}}>test</button>
</script>
js
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
test:null,
model: function() {
this.set("test",App.Person.create({firstName:"my fname",lastName:"my lastname"}));
return this.get("test");
}
,
actions:{
test:function(){
this.get("test").set("firstName","lallalal");
}
}
});
Ember.Handlebars.helper('fullName', function(person) {
return "fullName:"+person.get('firstName') + ' ' + person.get('lastName');
}, 'firstName', 'lastName');
Ember.Handlebars.helper('fullName2', function(person) {
return "fullName:"+person.get('firstName') + ' ' + person.get('lastName');
});
App.Person = Ember.Object.extend({
firstName:"",
lastName:""
});

How to read additional data within handlebars block expression template?

My html document will have div container which gets populated with handlebars template name 'relatedVideosTemplate' on execution.
<div id="relVideos"></div>
Below anonymous function will make ajax request and pass the data to handlebar template which loops over all items in data object to construct related videos UI.
(function(options) {
var defualt = {
defaultThumb: "/url/to/default/thumbnail/",
apiURL: '/path/to/api/url'
};
options = options || {};
options = $.extend(true, defaults, options);
// handlebars template for the related video carousel
var relatedVideosTemplate : "<h3>Related Videos</h3>" +
"<ul class=\"related-videos\">" +
"{{#foreach items}}<li class=\"video {{#if $last}} last{{/if}}\">" +
"<a href=\"/video/?videoid={{id}}\" class=\"image\">" +
"<img alt=\"{{name}}\" {{#if videoStillURL}}src=\"{{videoStillURL}}\"{{else}}src=\"{{defaultVideoThumb}}\"{{/if}} width=\"90\" height=\"75\" data-id=\"{{id}}\" onerror=\"this.src='{{defaultVideoThumb}}';\" />" +
"<span class=\"video-time\">{{length}}</span></a>" +
"<div class=\"info\"><h5>{{name}}</h5>" +
"<span class=\"published-date\">{{publishedDate}}</span>" +
"{{#if playsTotal}}<span class=\"video-views\">{{playsTotal}} views</span>{{/if}}" +
"</div></li>{{/foreach}}" +
"</ul>",
template, relVideosHTML;
$.ajax({
url: options.apiURL,
success: function(data) {
template = Handlebars.compile(relatedVideosTemplate);
relVideosHTML = template(data);
$("#relVideos").html( relVideosHTML );
}
});
});
Its very likely the video still image (thumbnail) for some videos will return 404 and in that case I use onerror event on image tag to replace it with default thumbnail.
Is there a way to pass this default thumbnal value as object to handlebars block expression template ?
I don't want to amend the data object to have 'defaultThumb' property for all items. Like below...
for ( i = 0, max = data.items.length; i < max; i++) {
// Adding new property to each item in data object
data.items[i].defaultThumb = options.defaultThumb;
};
It seems to me amending data property in above loop is non efficient as the defaultThumb is same across all videos which return 404 for still(thumb) image.
Why not set defaultVideoThumb once at the top level and then reference it as {{../defaultVideoThumb}} inside the loop? Something like this in the template:
<img
{{#if videoStillURL}}src="{{videoStillURL}}"{{else}}src="{{../defaultVideoThumb}}"{{/if}}
width="90" height="75"
onerror="this.src='{{../defaultVideoThumb}}'
>
and then in the JavaScript:
data.defaultVideoThumb = '...';
var html = template(data);
Demo: http://jsfiddle.net/ambiguous/9ecx3/

Categories

Resources