How i can send data between controllers AngularJS - ionic-framework

How i can send data between controllers AngularJS in my occasion?
I wanna send result of scanned qr code into things[] and,of course, show it.
I'm beginner in AngularJS and JavaScript and making this program just for me
App.js:
var MKscanner = angular.module('starter', ['ionic', 'ngCordova', 'ngStorage'])
MKscanner.controller('scanBarCtrl', function($scope, $cordovaBarcodeScanner) {
$scope.input ={
MyText : ''
};
$scope.scanBarcode = function() {
$cordovaBarcodeScanner.scan(
{
preferFrontCamera : false,
orientation : 'portrait'
}).then(function (result) {
alert(result.text);
},
function (error) {
alert('Scanning failed: ' + error);
});
};
});
MKscanner.factory ('StorageService', function ($localStorage) {
$localStorage = $localStorage.$default({
things: []
});
var _getAll = function () {
return $localStorage.things;
};
var _add = function (thing) {
$localStorage.things.push(thing);
}
var _remove = function (thing) {
$localStorage.things.splice($localStorage.things.indexOf(thing), 1);
}
return {
getAll: _getAll,
add: _add,
remove: _remove
};
});
MKscanner.controller( 'MainCtrl', function ($scope, StorageService) {
$scope.things = StorageService.getAll();
$scope.add = function (newThing) {
StorageService.add(newThing);
};
$scope.remove = function (thing) {
StorageService.remove(thing);
};
});
<div ng-controller="MainCtrl">
<div class="list">
<div class="item item-input-inset">
<label class="item-input-wrapper">
<input type="text" placeholder="Save your own text" ng-model="newThing">
</label>
<button class="button button-clear button-positive icon" ng-click="add(newThing)">
<i class="ion-ios-plus-outline"></i> Add
</button>
</div>
</div>
<ion-list show-delete="false" can-swipe="true">
<ion-item ng-repeat="thing in things">
{{thing}}
<ion-option-button class="button-assertive ion-trash-b" ng-click="remove(thing)"></ion-option-button>
</ion-item>
</ion-list>
</div>

You can share data between controllers using $emit and $broadcast :
These events can be used to send data as well, The classic example is given below. You can share data any controller in the app.
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="sendData();"></button>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
function sendData($scope) {
var arrayData = [1,2,3];
$scope.$emit('someEvent', arrayData);
}
});
app.controller('yourCtrl', function($scope, $http) {
$scope.$on('someEvent', function(event, data) {
console.log(data);
});
});
</script>

Related

Ionic 1 change text on template dynamically

I am trying to modify an ionic 1 project where I need to dynamically change the text on a tempate when it opens.
In the controller.js I have:
//Settings
$scope.settingsData = {};
$ionicModal.fromTemplateUrl('templates/settings.html', {
scope: $scope
}).then(function(modal) {
$scope.modal2 = modal;
});
$scope.closeSettings = function() {
$scope.modal2.hide();
};
$scope.settings = function() {
$scope.modal2.show();
};
$scope.doSettings = function() {
console.log('Doing Settings', $scope.settingsData);
$timeout(function() {
$scope.closeSettings();
}, 1000);
};
The template looks like this:
<ion-modal-view>
<ion-header-bar>
<h1 class="title">App Settings</h1>
<div class="buttons">
<button class="button button-clear" ng-click="closeSettings()">Close</button>
</div>
</ion-header-bar>
<div id="myid">Text in here needs to be replaced with something when it opens</div>
</div>
</ion-content>
</ion-modal-view>
So if I have a variable:
var myvar = 'Something to replace';
Then when the template opens the var above could be the text in div myid which is in the template
How can this be done?
i'll try to answer your question.
in your controller :
$scope.myvar = 'new text here !';
in your html file :
<div id="myid">{{myvar}}</div>

How can I disable an array of days in 'date-picker' when install "element-ui": "^2.3.7"?

I installed "element-ui": "^2.3.7" and I use it in my Vue component :
<el-date-picker
v-model="valueDateTimeOrder"
type="daterange"
align="right"
unlink-panels
range-separator="To"
start-placeholder="Start date"
end-placeholder="End date"
:picker-options = "pickerOptions">
</el-date-picker>
in data:
pickerOptions: {
disabledDate(time) {
return time.getTime() > Date.now();
},
}
It's works perfect. But when I want to disable all in an array, I don't know how to do it. Because the array only exist after get api. But data is done after all this component, it cannot wait call the range. Help me to set picker-options. Thanks
I think this can help you.
var app = new Vue({
el: '#app',
data() {
var vm = this;
return {
disabledDates: [],
pickerOptions1: {
disabledDate(time) {
time = moment(time).format('YYYY-MM-DD');
return vm.disabledDates.indexOf(time)>-1;
}
},
value1: '',
val: ''
};
},
methods: {
appendDate () {
this.disabledDates.push(this.val);
this.$refs.picker.unmountPicker();
this.$refs.picker.mountPicker();
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.min.js"></script>
<link href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" rel="stylesheet"/>
<div id="app" style="height:500px;">
<div class="block">
<el-date-picker
ref="picker"
v-model="value1"
type="date"
:picker-options="pickerOptions1"
placeholder="select date">
</el-date-picker>
<div>
disabledDates:{{disabledDates}}<br>
<input type="text" v-model="val"><button #click="appendDate">append date into disabled date array(format:YYYY-MM-DD)</button>
</div>
</div>
</div>

render data inserted to collection in react component

My entire application is built on different react classes and displayed like this:
MainLayout = React.createClass({
render() {
return (
<div id="body">
<Header />
<main className="container">{this.props.content}</main>
<Footer />
</div>
);
}
});
All my front-end is built in react classes like the one below:
InsertData = React.createClass({
insertToCollection(event) {
event.preventDefault();
console.log(this.state.message + " state med message");
var content = Posts.find().fetch();
Posts.insert({
Place: $("post1").val(),
Type: $("post2").val(),
dateAdded: new Date(),
});
},
handleChange(event) {
this.setState({
message: event.target.value
})
console.log(this.state + " mer state her");
function insert(event) {
event.preventDefault();
console.log("added stuff");
}
},
render() {
return (
<div>
<form onSubmit={this.insertToCollection}>
<input type='text' placeholder="Select a restaurant" className="input-field"
onChange={this.handleChange} id="post1"/>
<input type='text' placeholder="What type of food they have" className="input-field"
onChange={this.handleChange} id="post2"/>
<button className="waves-effect waves-light btn btn-block" onChange={this.insert}> Submit </button>
</form>
<DisplayData />
</div>
);
}
});
Insert data to my collection works fine. I would like to render the inserted data onto the page from the <DisplayData /> component:
DisplayData = React.createClass({
render(){
var posts = Posts.find().fetch();
var postList = posts.map(function(posts){
return posts;
})
return <p> Your collection </p>
}
});
I'm rather stuck here, and not really sure how to iterate through the collection and render it in a list-structure for example. Here is my collection so far:
Posts = new Mongo.Collection('posts');
Posts.allow({
insert: function(){
return true;
},
update : function(){
return true;
},
remove : function(){
return true;
}
});
Here is a demo of how you can approach this: http://codepen.io/PiotrBerebecki/pen/bwmAvJ
I'm not sure about the format of your posts collection, but assuming that it is just a regular array, for example var posts = ['One', 'Two'];, you can render the individual post as follows:
var DisplayData = React.createClass({
render(){
var posts = ['One', 'Two'];
var renderPosts = posts.map(function(post, index) {
return (
<li key={index}>{post}</li>
);
});
return (
<div>
<p> Your collection </p>
<ul>
{renderPosts}
</ul>
</div>
);
}
});
Here is the full code from my codepen.
var InsertData = React.createClass({
insertToCollection(event) {
event.preventDefault();
console.log(this.state.message + " state med message");
var content = Posts.find().fetch();
Posts.insert({
Place: $("post1").val(),
Type: $("post2").val(),
dateAdded: new Date(),
});
},
handleChange(event) {
this.setState({
message: event.target.value
})
console.log(this.state + " mer state her");
function insert(event) {
event.preventDefault();
console.log("added stuff");
}
},
render() {
return (
<div>
<form onSubmit={this.insertToCollection}>
<input type='text' placeholder="Select a restaurant" className="input-field"
onChange={this.handleChange} id="post1"/>
<input type='text' placeholder="What type of food they have" className="input-field"
onChange={this.handleChange} id="post2"/>
<button className="waves-effect waves-light btn btn-block" onChange={this.insert}> Submit </button>
</form>
<DisplayData />
</div>
);
}
});
var DisplayData = React.createClass({
render(){
var posts = ['One', 'Two'];
var renderPosts = posts.map(function(post, index) {
return (
<li key={index}>{post}</li>
);
});
return (
<div>
<p> Your collection </p>
<ul>
{renderPosts}
</ul>
</div>
);
}
});
ReactDOM.render(
<InsertData />,
document.getElementById('app')
);
You need to pass posts to your view component DisplayData as props, so in this case after you inserted a post, you should update your state in the InsertData component. Actually it would be better if you do the insertion login inside a service rather than the component itself, but for simplicity right now you can check the following code:
InsertData = React.createClass({
getInitialState: function() {
return {posts: []}; // initialize the state of your component
},
insertToCollection(event) {
event.preventDefault();
console.log(this.state.message + " state med message");
var content = Posts.find().fetch();
Posts.insert({
Place: $("post1").val(), // better to retrieve these values from state. You can use `handleChange` method to keep track of user inputs
Type: $("post2").val(),
dateAdded: new Date(),
}, function(err, data){
var posts = this.state.posts || [];
posts.push(data);
this.setState({posts: posts}); //after setting the state the render method will be called again, where the updated posts will be rendered properly
});
},
handleChange(event) {
this.setState({
message: event.target.value
})
console.log(this.state + " mer state her");
function insert(event) {
event.preventDefault();
console.log("added stuff");
}
},
render() {
return (
<div>
<form onSubmit={this.insertToCollection}>
<input type='text' placeholder="Select a restaurant" className="input-field"
onChange={this.handleChange} id="post1"/>
<input type='text' placeholder="What type of food they have" className="input-field"
onChange={this.handleChange} id="post2"/>
<button className="waves-effect waves-light btn btn-block" onChange={this.insert}> Submit </button>
</form>
<DisplayData posts={this.state.posts}/>
</div>
);
}
});
var DisplayData = React.createClass({
render(){
var posts = this.props.posts || [];
var renderPosts = posts.map(function(post, index) {
return (
<li key={index}>{post}</li>
);
});
return (
<div>
<p> Your collection </p>
<ul>
{renderPosts}
</ul>
</div>
);
}
});

ionic, select input (type number) content on click / focus

In my Ionic app, as you can see, this "select-on-focus" directive doesn't work in iOS...
Here's a video:
https://youtu.be/_bOWGMGesgk
Here's the code:
<div class="wrapperFlex withNextButton">
<div class="itemTitle">
<div class="text">
{{'paramQuestions.weight' | translate }}
</div>
</div>
<div id="weightdata" class="itemParameters weightdataclass row">
<input class="weightinput" type="number" name="userweight" ng-min="{{data.minWeight}}" ng-max="{{data.maxWeight}}" ng-model="data.realWeight" ng-change="updateViewGenVol(data.weightunit, data.userweight, data.BLfactorValue);saveUserWeight()" select-on-focus required></input>
<div class="weightunitradios">
<ion-checkbox class="checkboxes checkbox-blueboardline" ng-model="data.weightunit" ng-true-value="'kg'" ng-false-value="'lbs'" ng-change="saveWeightUnit(); changeMinMax(); convertWeightInput(); saveUserWeight();">kg</ion-checkbox>
<ion-checkbox class="checkboxes checkbox-blueboardline" ng-model="data.weightunit" ng-true-value="'lbs'" ng-false-value="'kg'" ng-change="saveWeightUnit(); changeMinMax(); convertWeightInput(); saveUserWeight();">lbs</ion-checkbox>
</div>
</div>
</div>
directives.js:
.directive('selectOnFocus', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var focusedElement = null;
element.on('focus', function () {
var self = this;
if (focusedElement != self) {
focusedElement = self;
$timeout(function () {
self.select();
}, 10);
}
});
element.on('blur', function () {
focusedElement = null;
});
}
}
})

Error submitting form data using knockout and mvc

#model NewDemoApp.Models.DemoViewModel
#{
ViewBag.Title = "Home Page";
}
#*<script src="#Url.Content("~/Scripts/jquery-1.9.1.min.js")" type="text/javascript"></script>*#
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script src="#Url.Content("~/Scripts/knockout-3.3.0.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script type="text/javascript">
var viewModel;
var compViewModel, userViewModel;
$(document).ready(function () {
$(".wizard-step:visible").hide();
$(".wizard-step:first").show(); // show first step
$("#back-step").hide();
var result = #Html.Raw(Json.Encode(Model));
var viewModel = new DemoViewModel(result.userViewModel);
//viewModel.userViewModel.FirstName = result.userViewModel.FirstName;
//viewModel.userViewModel.LastName = result.userViewModel.LastName;
//viewModel.userViewModel.State = result.userViewModel.State;
//viewModel.userViewModel.City = result.userViewModel.City;
ko.applyBindings(viewModel);
});
var userVM = function(){
FirstName = ko.observable(),
LastName = ko.observable(),
State = ko.observable(),
City = ko.observable()
};
function DemoViewModel(data) {
var self = this;
self.userViewModel = function UserViewModel(data) {
userVM.FirstName = data.FirstName;
userVM.LastName = data.LastName;
userVM.State = data.State;
userVM.City = data.City;
}
self.Next = function () {
var $step = $(".wizard-step:visible"); // get current step
var form = $("#myFrm");
var validator = $("#myFrm").validate(); // obtain validator
var anyError = false;
$step.find("input").each(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
if (anyError)
return false; // exit if any error found
if ($step.next().hasClass("confirm")) { // is it confirmation?
$step.hide().prev(); // hide the current step
$step.next().show(); // show the next step
$("#back-step").show();
$("#next-step").hide();
//$("#myFrm").submit();
// show confirmation asynchronously
//$.post("/wizard/confirm", $("#myFrm").serialize(), function (r) {
// // inject response in confirmation step
// $(".wizard-step.confirm").html(r);
//});
}
else {
if ($step.next().hasClass("wizard-step")) { // is there any next step?
$step.hide().next().fadeIn(); // show it and hide current step
$("#back-step").show(); // recall to show backStep button
$("#next-step").show();
}
}
}
self.Back = function () {
var $step = $(".wizard-step:visible"); // get current step
if ($step.prev().hasClass("wizard-step")) { // is there any previous step?
$step.hide().prev().fadeIn(); // show it and hide current step
// disable backstep button?
if (!$step.prev().prev().hasClass("wizard-step")) {
$("#back-step").hide();
$("#next-step").show();
}
else {
$("#back-step").show();
$("#next-step").show();
}
}
}
self.SubmitForm = function (formElement) {
$.ajax({
url: '#Url.Content("~/Complaint/Save")',
type: "POST",
data: ko.toJS(self),
done: function (result) {
var newDiv = $(document.createElement("div"));
newDiv.html(result);
},
fail: function (err) {
alert(err);
},
always: function (data) {
alert(data);
}
});
}
self.loadData = function () {
$.get({
url: '#Url.Content("~/Complaint/ViewComplaint")',
done: function (data) {
debugger;
alert(data);
self.compViewModel(data);
self.userViewModel(data);
},
fail: function (err) {
debugger;
alert(err);
},
always: function (data) {
debugger;
alert(data);
}
});
}
}
</script>
<form class="form-horizontal" role="form" id="myFrm">
<div class="container">
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6">
<div class="wizard-step">
</div>
<div class="wizard-step" >
<h3> Step 2</h3>
#Html.Partial("UserView", Model.userViewModel)
<div class="col-md-3"></div>
<div class="col-md-6">
<input type="submit" id="submitButton" class="btn btn-default btn-success" value="Submit" data-bind="click: SubmitForm" />
</div>
<div class="col-md-3"></div>
</div>
<div class="wizard-step">
<h3> Step 3</h3>
</div>
<div class="wizard-step confirm">
<h3> Final Step 4</h3>
</div>
</div>
<div class="col-md-3"></div>
</div>
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6">
<input type="button" id="back-step" class="btn btn-default btn-success" value="< Back" data-bind="click: Back" />
<input type="button" id="next-step" class="btn btn-default btn-success" value="Next >" data-bind="click: Next" />
</div>
<div class="col-md-3"></div>
</div>
</div>
</form>
I am able to get the data from controller and bind it using knockout. There is a partial view that loads data from controller. But when submitting the updated data, I do not get the data that was updated, instead getting error that "FirstName" property could not be accessed from null reference. I just need to get pointers where I am going wrong especially the right way to create ViewModels and use them.
When you are submitting the form in self.SubmitForm function you are passing Json object which is converted from Knockout view model.
So make sure you are providing the data-bind attributes in all input tags properly. If you are using Razor syntax then use data_bind in Html attributes of input tags.
Check 2-way binding of KO is working fine. I can't be sure as you have not shared your partial view Razor code.
Refer-
http://knockoutjs.com/documentation/value-binding.html
In Chrome you can see what data you are submitting in Network tab of javascript developer console. The Json data that you are posting and ViewModel data structure you are expecting in controller method should match.
You can also change the parameters to expect FormCollection formCollection and check what data is coming from browser when you are posting.