storing specific element in knockout.js viewmodel (array) - javascript

I want to parse specific element from an existing viewModel and put it into a new array.
I have an applications viewModel which has tons of information of applicants. It is called in the following way:
self.applications = ko.observableArray(#Html.Json(Model.ApplicationCompatibilities.Select(o => o.JsonForm)) || []);
So the "application" object has several elements in it as shown in the attached image above.
What I wanted to do was, I wanted to retrieve only the "applicationKey" element into a new array. So what I did was :
self.previewApplication = ko.computed(function () {
return ko.utils.arrayFilter(self.applications(), function (i) {
return i.application.applicationKey;
});
});
I intended to loop through the "self.applications()" viewModel and return only the "application.applicationKey". But what I actually get by doing that is:
I am just getting the same "applications" object inside the new viewModel.
How can I get an array of only the "application.applicationKey" ?
Thanks! Please Help!
EDIT:
This works now! Now my viewModel.previewApplication() gives me a list of applicationKey's. Now what I want to do is, I want to add a link that loads a modal. And inside that modal I want to display the specific "application" that has a specific "applicationKey"
For example, the link to the modal will look like this:
<a href="#" data-toggle="modal" data-target="#previewApplicantModal" data-bind="attr: { 'data-applicationKey': application.applicationKey }">
Preview Application
</a>
So If I inspect the element of the link, it has a new data-binding:
<a href="#" data-toggle="modal" data-target="#previewApplicantModal" data-bind="attr: { 'data-applicationKey': application.applicationKey }" data-applicationkey="abc976cfx">
Preview Application
</a>
Finally I want to loop through the "application" object and return only "one" element of the object that has "abc976cfx" as its applicationKey.
Is there an easy way of doing this? I attached a screenshot for better explanation.

arrayFilter filters the array and the function returns true or false if the item matches your filter criteria or not. You want arrayMap instead.

Related

Firebase table - javascript

I have a firebase database with some information in it, that I just constructed a table:
rootRef.on("child_added", snap => {
var name = snap.child("leagueName").val();
var code = snap.key;
$("#table_body").append("<tr><td> <button id="+code+" class='mdl-button mdl-js-button'>"+ name +" </button></td></tr>");});
So now I have arbitrary number of rows at my table, each has a button with it's unique ID.
next step is that I want each of them to be a link to some other page.
Is there a way to retrieve these ID's to create a js click function with them?
I mean I don't know what these ID's are and how many of them will be, since this is something the user will enter.
Maybe there's another more efficient way?
I think you may be looking for:
$('#table_body').on('click', 'btn', function() {
alert($(this).attr('id'));
document.location = 'https:/your.new.url/leagues/' + $(this).attr('id');
});
Of course if you want the elements to just be a link to another page, you should really consider making them <a href='...'> elements, as those are the idiomatic way to model links to pages. And in that case, you could also simply inject the keys when you generate the row in the table:
$("#table_body").append("<tr><td> <a id="+code+" href='https:/your.new.url/leagues/"+code+"' class='mdl-button mdl-js-button'>"+ name +" </button></td></tr>");});

Binding and Creating scope variables dinamically in AngularJS

Context: I am building a helper with dynamically editable help sections (each one with its title and content). I have an "Add" button at the bottom of the last help existing section to add more help sections to this helper.
I am binding a variable $scope.helpVisible to set the visibility of the section to ReadOnly or Editable with ng-show and ng-hide.
Problem: When I click on "Add" to add a new help section to the helper, I need a new variable to set the visibility of this new element (a div). The problem is that it takes the previous variable to decide the visibility of this new element.
I have tried to create a list $scope.listOfVilibilities pushing a new item every time I create a new help section.
How can I create new variables in the scope "on the fly" and bind them in the view?
Try creating objects into a array and use ngRepeat directive to add this new object into view.
for example controller:
function MyCtrl($scope) {
$scope.list = [];
$scope.add = function(){
$scope.list.push({value:void(0), disabled: false});
}
$scope.delete = function(value){
$scope.list = _.remove($scope.list, function(n){
return n.value !== value;
});
}
}
Important! I used lodash library in the delete function. Doc. here
The HTML look like this:
<div ng-controller="MyCtrl">
<button ng-click="add()">
Add
</button>
<ul>
<li ng-repeat="some in list">
<input ng-model="some.value" ng-disabled="some.disabled"/>
<button ng-click="some.disabled = !some.disabled">
{{!some.disabled}}
</button>
<button ng-click="delete(some.value)">
Delete
</button>
</li>
</ul>
</div>
Take a look to this example live in jsfiddle.

Polymer, evaluate element based off object

I am using the tile example from polymers neon elements - and I am trying to make each expanded tile unique. My first try on how to do this was to pass a string in with the grid items like
{
value: 1,
color: 'blue',
template: 'slide-1'
}
And have that element be evaluated when rendered in a new element something like this. (this is the card template itself)
<template>
<div id="fixed" class$="[[_computeFixedBackgroundClass(color)]]"></div>
<div id="card" class$="[[_computeCardClass(color)]]">
<[[item.template]]></[[item.template]]>
</div>
This does not work - however I am wondering if there is some way to do this so I can load custom elements for the content of each card. For reference -https://elements.polymer-project.org/elements/neon-animation?view=demo:demo/index.html&active=neon-animated-pages , it is the grid example and I am trying to replace the content of each card once it is clicked on ( the fullsize-page-with-card.html, here is all the html for it - https://github.com/PolymerElements/neon-animation/tree/master/demo/grid ). Is this the wrong way of approaching this? Or maybe I have some syntax wrong here. Thanks!
Edit : OK, So I can send it through if i add it to the click to open the card like so
scope._onTileClick = function(event) {
this.$['fullsize-card'].color = event.detail.data.color;
this.$['fullsize-card'].template = event.detail.data.template;
this.$.pages.selected = 1;
};
and in the card's properties like so
template: {
type: String
},
So I can then evaluate it as [[template]] , however - the question still remains how to call a custom element (dynamically) using this string. I could pass a couple of properties and fill in a card or form so they are unique, but i think I would have much more creative freedom if I could call custom elements inside each card.
I have an element that allows referenced templates. There are a couple of others other there, but this one also allows data bindings to work: https://github.com/Trakkasure/dom-bindref

Add new AngularJS variables with JavaScript

I'm trying to make a dynamic form with AngularJS and JavaScript. The objective is to add how many inputs the user need and transform all those inputs in AngularJS variables that print it on body. So I got that code:
$(function(){
var number = 1;
$('a.add').click(function(e){
e.preventDefault();
$('#this_div_contains_settings').append('<input type="text" name="example'+number+'" ng-model="example'+number+'" placeholder="Anything">');
number++;
});
$('#this_div_contains_settings').on('click','a.design_button', function(e){
e.preventDefault();
$(this).parent().remove();
});
});
This function add a INPUT on my DIV with the different ng-model every time it run.
The problem is, it just work's if the {{example1}} is already on my BODY, if I add it later with another function, it just doesn't work.
I'm new with AngularJS, so I didn't understand if I need to "refresh" the AngularJS everytime I add new variable or something like that.
Any help will be appreciated :)
Using jQuery is the wrong way to solve this problem. Instead, create an array inside of your controller that will hold the models for all of these inputs.
Depending on how you define/create your controllers, $scope may be replaced with this
$scope.examples = [];
Next, create a function that will add a new example to the array:
$scope.addExample = function () {
$scope.examples.push("");
}
Now, in your template, create the inputs using an ng-repeat:
<div id="this_div_contains_settings">
<input ng-repeat="example in examples" type="text" name="example" ng-model="example" placeholder="Anything">
</div>
and have your "add" button call your addExample function on click:
<a class="add" ng-click="addExample()">Add Example</a>
Finally, remove all of the code that was included in your question.
And for your .design_button that removes all the examples, that's easy too:
<a class="design_button" ng-click="examples = []">remove all examples!</a>
by that same concept, you could even remove the need for the addExample function, however i tend to keep logic in the controller (well, actually in the services, but that's another topic) anyway rather than putting it in the template.

AngularJS on top of server generated content

I'm looking for a way to integrate something like ng-repeat with static content. That is, to send static divs and to have them bound to JS array (or rather, to have an array constructed from content and then bound to it).
I realize that I could send static content, then remove and regenerate the dynamic bits. I'd like not to write the same divs twice though.
The goal is not only to cater for search engines and people without js, but to strike a healthy balance between static websites and single page applications.
I'm not sure this is exactly what you meant, but it was interesting enough to try.
Basically what this directive does is create an item for each of its children by collecting the properties that were bound with ng-bind. And after it's done that it leaves just the first child as a template for ng-repeat.
Directive:
var app = angular.module('myApp', []);
app.directive('unrepeat', function($parse) {
return {
compile : function (element, attrs) {
/* get name of array and item from unrepeat-attribute */
var arrays = $parse(attrs.unrepeat)();
angular.forEach(arrays, function(v,i){
this[i] = [];
/* get items from divs */
angular.forEach(element.children(), function(el){
var item = {}
/* find the bound properties, and put text values on item */
$(el).find('[ng-bind^="'+v+'."]').each(function(){
var prop = $(this).attr('ng-bind').split('.');
/* ignoring for the moment complex properties like item.prop.subprop */
item[prop[1]] = $(this).text();
});
this[i].push(item);
});
});
/* remove all children except first */
$(element).children(':gt(0)').remove()
/* add array to scope in postLink, when we have a scope to add it to*/
return function postLink(scope) {
angular.forEach(arrays, function(v,i){
scope[i] = this[i];
});
}
}
};
});
Usage example:
<div ng-app="myApp" >
<div unrepeat="{list:'item'}" >
<div ng-repeat="item in list">
<span ng-bind="item.name">foo</span>
<span ng-bind="item.value">bar</span>
</div>
<div ng-repeat="item in list">
<span ng-bind="item.name">spam</span>
<span ng-bind="item.value">eggs</span>
</div>
<div ng-repeat="item in list">
<span ng-bind="item.name">cookies</span>
<span ng-bind="item.value">milk</span>
</div>
</div>
<button ng-click="list.push({name:'piep', value:'bla'})">Add</button>
</div>
Presumable those repeated divs are created in a loop by PHP or some other backend application, hence why I put ng-repeat in all of them.
http://jsfiddle.net/LvjyZ/
(Note that there is some superfluous use of $(), because I didn't load jQuery and Angular in the right order, and the .find on angular's jqLite lacks some features.)
You really have only one choice for this:
Render differently for search engines on the server, using something like the approach described here
The problem is you would need to basically rewrite all the directives to support loading their data from DOM, and then loading their templates somehow without having them show up in the DOM as well.
As an alternative, you could investigate using React instead of Angular, which (at least according to their website) could be used to render things directly on the web server without using a heavy setup like phantomjs.

Categories

Resources