Kendo MVVM Binding to Self Executing Anonymous Module Function - html

I'm working with the Kendo UI MVVM and I'm trying to bind it to a self executing anonymous modular function. Long story short, it's only kind of working. The module is being updated if I inspect the page but the UI isn't. All I'm using is a short HTML file with a script tag to wire up the MVVM and an external JavaScript file to bring the module in.
HTML and JS on page
<!-- Adding information -->
<input data-bind="value: DemoField" />
<!-- Update Button -->
<button data-bind="events: { click: updateModule }">Update</button>
<!-- Trying to update this field -->
<input data-bind="value: module.Model.Demo.DemoField" />
<!-- Observable -->
<script type="text/javascript">
var model = kendo.observable(
{
DemoField: "",
updateModule: function () {
module.updateInformation({
demoField: this.get("DemoField")
)};
}
},
module
);
kendo.bind($("#form"), invoiceModel);
</script>
Module JS file
var module = (function () {
// private information
var _demo = (function () {
var _demoObject = {},
_demoField = null;
Object.defineProperty(_demoObject, "DemoField", {
get: function () { return _demoField; }
});
_demoObject.updateInformation = function (updatedObject) {
if (updatedObject.demoField) {
_demoField = updatedObject.demoField;
}
};
return _demoObject;
}());
var _model = { Demo: _demo };
// public information
return {
Model: _model
updateInformation: _demo.updateInformation
}
}());
If I enter "module.Model.Fields.FieldName" in the inspector, I see the information I'm expecting, but the UI just isn't playing nice. I've been to many pages on Telerik's website and I've consulted Google, but typically my searches yield little to no results and the results I do get are less than useful.
My thoughts are that kendo won't observe a module like it would a regular property, but then again I haven't worked with any kind of JS module before and I'm very new to MVVM.

Your thoughts are correct. Kendo will not observe a nested property, even if it is not nested you always have to use "get" and "set" words, for reference in Angular you don't need to do that.
So your code should look something like that:
<input data-bind="value: DemoField" />
<!-- Update Button -->
<button data-bind="events: { click: updateModule }">Update</button>
<!-- Trying to update this field -->
<input data-bind="value: updatedValue" />
And the view Model:
var model = kendo.observable({
DemoField: "",
updateModule: function () {
module.updateInformation({
demoField: this.get("DemoField")
});
this.set("updatedValue", module.Model.Demo.DemoField);
},
updatedValue: "",
});
kendo.bind($("#form"), model);
Here is a link to dojo with working example:
http://dojo.telerik.com/UzUhi

Related

Polymer/Lit-Element - Braintree gateway integration - Web Component problem

I am trying to integrate Braintree payment gateway to Vaadin 14 which is using Polymer for its frontend.
Basically we have a custom Vaadin front-end view to load script https://js.braintreegateway.com/web/dropin/1.9.4/js/dropin.min.js :
And we call its method dropin.create as below:
import{PolymerElement}from'#polymer/polymer/polymer-element.js';
import'#polymer/iron-icon/iron-icon.js';
import{html}from'#polymer/polymer/lib/utils/html-tag.js';
import '#webcomponents/webcomponentsjs/webcomponents-loader.js';
import'#polymer/polymer/polymer-legacy.js';
import'#polymer/iron-flex-layout/iron-flex-layout.js';
import{mixinBehaviors}from'#polymer/polymer/lib/legacy/class.js';
import{Polymer}from'#polymer/polymer/lib/legacy/polymer-fn.js';
import{setTouchAction}from'#polymer/polymer/lib/utils/gestures.js';
import{afterNextRender}from'#polymer/polymer/lib/utils/render-status.js';
import'#vaadin/vaadin-text-field/vaadin-text-field.js';
import { sharedStyles } from './drop-in.js';
let dropin = require('braintree-web-drop-in');
class BrainTreeVaadin extends PolymerElement {
<vaadin-vertical-layout class="main-div-layout-boder padding5">
<form id="paymentForm" method="post" action="/checkout" class="main-screen-vert-layout-row">
<div id="containPayment" class="main-screen-vert-layout-row">
<div id="btDropin" class="main-screen-vert-layout-row"></div>
</div>
<vaadin-text-field id="nonce" value={{valueNonce}} hidden></vaadin-text-field>
<vaadin-button id="butPayment" theme="theme-button-02" class="button-row">Payment</vaadin-button>
</form>
</vaadin-vertical-layout>
createFormPayment(){
let form = this.$.paymentForm;
let butPayment = this.$.butPayment;
let btDropin = this.$.btDropin;
let textNonce = this.$.nonce;
dropin.create({
authorization: this.clientToken,
container: btDropin,
card: {
cardholderName: {
required: true
}
},
paypal: {
flow: 'vault',
currency: 'USD'
},
paypalCredit: {
flow: 'vault',
currency: 'USD'
}
}
}
}
However we get error as below image:
Reason that internally, the main script dropin.min.js includes other script https://www.paypalobjects.com/api/checkout.min.js and called other methods from this new JS.
Accessing methods in checkout.min.js got error because checkout.min.js can’t get id of html elements (here is buttons) using javascript reference style "#...".
Braintree uses JS style #element_id to pass a html div element as argument to method: braintree.dropin.create(..., container: '#bt-dropin').
Below is Braintree example code (take note on method "braintree.dropin.create", it takes '#bt-dropin' as input):
<div class="bt-drop-in-wrapper">
<div id="bt-dropin"></div>
</div>
<div th:include="fragments/homefooter :: footer"></div>
<script src="https://js.braintreegateway.com/web/dropin/1.9.4/js/dropin.min.js"></script>
<script th:inline="javascript">
/*<![CDATA[*/
var form = document.querySelector('#payment-form');
var client_token = [[${clientToken}]];
braintree.dropin.create({
authorization: client_token,
container: '#bt-dropin',
paypal: {
flow: 'vault'
}
}, function (createErr, instance) {
form.addEventListener('submit', function (event) {
event.preventDefault();
$('#errorDiv').hide();
$('#serverSideErrorDiv').hide();
instance.requestPaymentMethod(function (err, payload) {
if (err) {
console.log('Error', err);
showError(err);
return;
}
// Add the nonce to the form and submit
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
});
});
And problem that Vaadin form (view) doesn’t understand javascript style: "#bt-dropin" to reference to a div element.
How to make Vaadin view understand JS style: "#element_id" ?
Update:
this is polymer problem, not Vaadin flow problem.
Update 2:
this is braintree problem, not polymer problem :)).
This is a issue of braintree due to lacking of supporting web components.
Below is workaround solution.
Braintree Git Issue
Workaround (remove space .io on URL):
https://codepen .io/braintree/pen/VrYXYW

Razor with kendoui text editor

I was trying to display Kendo UI text editor when check box is checked.
However it's not working, can you help me out..
#if (Model.IsAlert!=true)
{
<td>
#(Html.Kendo().Editor().Name("Explanation").HtmlAttributes(new { style = "display:show" }))
</td>
}
Your current approach will only render that/evaluate Model.IsAlert on the initial load of screen.
I would suggest removing the if statement, and defaulting this td to hidden, then change that depending on the properties in the model via a onChange event handler mapped to your checkbox control.
<td id="thingToHide" hidden="hidden">
#(Html.Kendo().Editor().Name("Explanation").HtmlAttributes(new { style = "display:show" }))
</td>
and some jquery code:
<script type="text/javascript">
$(document).ready(function () { // On page load method, check model and show textbox if needed
var model = #Html.Raw(Json.Encode(Model)); // get model example is taken from http://stackoverflow.com/questions/16361364/accessing-mvcs-model-property-from-javascript
if (model.IsAlert) { // If model IsAlert is true, show Explanation field
$("#thingToHide").show();
}
});
$("#YourCheckBoxId").on("change", function() {
$("#thingToHide").toggle();
});
</script>
Good luck Radha!

How to create a separate scope isolated from ng-repeat in Angular?

I am new to AngularJS and have some trouble understanding the concept of scope in Angular. I have read some posts on stackoverflow as well as online articles, which advise me to create a custom directive to create an isolate scope, but I am getting nowhere...
As for the project I'm working on, I am trying to make a button that when clicked, will trigger a textarea. However, because of ng-repeat, the textarea is triggered for all buttons while I click only one.
My .js file:
angular.module('myApp')
.controller('myCtrl', function ($scope, Question) {
scope.visible = false;
scope.toggle = function() {
scope.visible = !scope.visible;
};
.directive("myDirective", function () {
return {
scope: {
ngClick: '&',
ngShow: '&'
}
}
});
Here is my HTML file:
<ul>
<li ng-repeat="object in objectList">
<button type="text" myDirective ng-click="toggle()">Click</button>
<textarea myDirective ng-show="visible"></textarea>
</li>
</ul>
Angular is creating child (NOT isolated) scope when ng-repeating, try this out, when you ng-init a variable, it is only visible within that repeat div.
<div ng-repeat="i in [0,1,2,3,4,5,6,7,8,9]" ng-init="visible=false">
<button ng-click="visible=!visible">Toggle</button>
<h1 ng-show="visible">look at me!</h1>
</div>
Plunker
There is no need to use a directive. You need to use object in the foreach to refer each item in the loop.
Add visible to each object in objectList:
$scope.objectList = [
{ visible: false },
{ visible: false },
{ visible: false }
];
Then the toggle button will need to pass the object to toggle:
$scope.toggle = function (object) {
object.visible = !object.visible;
};
The ng-show will need to check object.visible and ng-click will need to pass the object:
<button type="text" ng-click="toggle(object)">Click</button>
<textarea ng-show="object.visible"></textarea>
Plunkr

AngularJS - Sharing Data between controllers from json

actually I get stucked since several days with following problem. I like to create a small app which loads data from a json file. The app should consist of 3 views !
Show a list of data
Edit view for changing current data
add view to store new data
Now I learned to use a service which provides data to each controller for each view.
But for the time my service works only with generated data within my variable thing.
How Can I change this that my service will provide data from .json file which may be edited and updated with any controller !
Thanks
Here is my code and plnker
<!doctype html>
<html ng-app="project">
<head>
<title>Angular: Service example</title>
<script src="http://code.angularjs.org/angular-1.0.1.js"></script>
<script>
var projectModule = angular.module('project',[]);
projectModule.factory('theService', function() {
return {
thing : [{"DATE" : "2014","IATA":"DUS","DUTY":"10:12"},
{"DATE" : "2015","IATA":"MIA","DUTY":"10:12"},
{"DATE" : "2017","IATA":"JFK","DUTY":"10:12"}]
};
/*
return {
thing:[function($http) {
return $http.get('data.json').then(function(response) {})
return response.data;
}]
};
*/
});
function FirstCtrl($scope, theService) {
$scope.thing = theService.thing;
$scope.name = "First Controller";
}
function SecondCtrl($scope, theService) {
$scope.someThing = theService.thing;
$scope.name = "Second Controller!";
}
</script>
</head>
<body>
<div ng-controller="FirstCtrl">
<h2>{{name}}</h2>
<div ng-repeat="show in thing">
<p>
<b>DATE </b>{{show.DATE}}
<b>IATA </b>{{show.IATA}}
<b>DUTY </b>{{show.DUTY}}
</p>
</div>
<div ng-controller="SecondCtrl">
<h2>{{name}}</h2>
<div ng-repeat="edit in someThing">
<p>
<input ng-model="edit.DATE"/>
<input ng-model="edit.IATA"/>
<input ng-model="edit.DUTY"/>
</p>
</div>
</div>
</body>
</html>
All you have to do is use $http service and return it:
getJson: function() {
return $http.get('data.json')
}
Then in your controller you use it like this:
service.getJson(function(data) {
$scope.thing = data;
})
To convert object to json you need to use angular.fromJson i angular.toJson
Angular Docs
After that you do:
$http.post('yourjson);
to replace your current json (save changes).
You should also redownload it (to have everything in sync) using $http.get as I described above.
I have found an example example. I hope it helps.

MVC 4 (razor) - Controller is returning a partialview but entire page is being updated

I'm new to MVC 4 and the Razor engine - so this might be a dumb question.
What I'm trying to achieve is I have a page with a drop down list and a button. Clicking the button calls the controller passing the value selected. The controller should return a partial view and only the bottom part of the page should be updated.
However I'm finding that the entire page gets replaced with just the partial view html. Ie. I get my list of results displaying but I lose my dropdownlist of projects and submit button. I tried including a reference to jquery and unobtrusive scripts (which I don't think I need to in MVC 4) but that doesn't change the page at all (ie. the dropdownlist and button stay there and no results are displayed).
Part of my View:
#using (Ajax.BeginForm("GetProjectStories", "MyController", new AjaxOptions{ UpdateTargetId = "projectUserStories"}))
{
<fieldset>
<legend>Select Project</legend>
<div>
#Html.DropDownList("ProjectReference", (IEnumerable<SelectListItem>)Model.ProjectList)
</div>
<p>
<input name="GetStoriesButton" type="submit" value="Get Stories" />
</p>
</fieldset>
}
#if (Model != null && Model.UserStories != null)
{
<div id="projectUserStories">
#{Html.RenderPartial("_UserStoryList", Model);}
</div>
}
My controller:
public ActionResult GetProjectStories(ProjectViewModel model)
{
var stories = MyService.GetProjectUserStories(model.ProjectReference).Results;
model.UserStories = stories;
return PartialView("_UserStoryList", model);
}
My partial view content just contains an html table and reference to the model.
How you planning to update projectUserStories, if code block could not be rendered, try this:
<div id="projectUserStories">
#if (Model != null && Model.UserStories != null)
{
Html.RenderPartial("_UserStoryList", Model);
}
</div>
Also check all required js files for Microsoft Ajax helpers, for example this:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
Also look at:
Using Ajax.BeginForm with ASP.NET MVC 3 Razor
MVC 3 - Ajax.BeginForm does a full post back
So I tried including that unobtrusive script, and fixing the fact I wasn't rendering that div if that object was null but it still wasn't working.
So I switched to using jquery.
<script src="#Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$('form').submit(function () {
var url = "#Url.Action("GetProjectStories", "MyController")";
var data = { selectedProject: $('#ProjectReference').val() };
$("#projectUserStories").load(url, data, function() {
});
return false;
});
});
</script>
#using (Html.BeginForm())
{
<fieldset>
<legend>Select Project</legend>
<div>
#Html.DropDownList("ProjectReference", (IEnumerable<SelectListItem>) Model.ProjectList)
</div>
<p>
<input name="GetStoriesButton" type="submit" value="Get Stories" />
</p>
</fieldset>
<div id="projectUserStories">
#{ Html.RenderPartial("_UserStoryList", Model); }
</div>
}