Ui-router, ng-repeat and ui state - javascript

I m developping an application in which I need to redirect the current user to a different state after a ressource creation.
Actually, I have a list of demands, and I need to show or create a quotation based on that demand.
Here's the view code :
<div class="landing-diags">
<div class="current-projects">
<div class="row project-summary" ng-repeat="demand in landingdiag.demandsList">
<div class="col-md-2 project-block first-block {{project.projectType}}">
<p class="project-strong">{{demand.user.firstname}} {{demand.user.lastname}}</p>
</div>
<div class="col-md-2 project-block">
<p class="project-strong">{{demand.creationDate | date:"dd/MM/yyyy"}}</p>
</div>
<div class="col-md-4">
</div>
<div class="col-md-2">
<div ng-if="!demand.quotation">
<button ng-click="landingdiag.createQuotation(demand)" class="btn btn-primary pull-right bar-btn">Create</button>
</div>
<div ng-if="demand.quotation">
<button ui-sref="app.state.concerned({id: demand._id})" class="btn btn-primary pull-right bar-btn">Show</button>
</div>
</div>
</div>
</div>
</div>
And here's the controller methods implied :
createQuotation (demand) {
this.DemandsService.createQuotation(demand).$promise.then((response) => {
this.redirectToQuote(demand);
});
}
redirectToQuote (demand) {
this.$state.transitionTo('app.state.concerned', {id: demand._id});
}
Problem
My problem is that I m never redirected when creating a quotation. If I console log the redirectToQuote method, I pass inside of it. So it seems that my problem is on the $state.go call.
However, when I try to redirect directly using the redirectToQuote method inside of my view on the "show" button like following :
<div ng-if="demand.quotation">
<button ng-click="landingdiag.redirectToQuote(demand)" class="btn btn-primary pull-right bar-btn">Accéder au devis</button>
</div>
I m well redirected to the concerned state

I am concerned about the this.redirectToQuote within createQuotation() which is called by then() as a callback. So the this object will definitely not be your controller.
Look at the first code snippet from todd: https://toddmotto.com/resolve-promises-in-angular-routes/
He is using bind.
You can also look at https://github.com/getify/You-Dont-Know-JS/tree/master/this%20%26%20object%20prototypes from awesome Kyle Simpson
or shorter from myself: http://blog.monkey-development.com/javascript/java/2015/12/18/javascript-this.html

Related

Check if json array is empty at store vuex

I want to show a button if my array of object has some data, so basilcy in my store(vuex) i defined a array like this:
state: {
document: []
},
i append data to this array from other components and i already checked that the data is appending right, no problem here.
So i want to show the button just if there is some data:
<div class="row margin-above">
<div class="panel panel-primary" v-for="section in this.$store.getters.getDocument">
<div class="panel-body quote" >
<p>{{section.key}}</p>
</div>
</div>
<div v-if="this.$store.getters.getDocument != '[]'">
<button class="btn btn-success btn-block">Create Document</button>
</div>
</div>
there is the button, i want to hide the whole div with the button if the condition matches, but it is not working the button is always there, any help?
Check its length property.
<div v-if="this.$store.getters.getDocument.length != 0">
<button class="btn btn-success btn-block">Create Document</button>
</div>
Or assign the vuex variable to null when there are no elements. Than this should work.
<div v-if="this.$store.getters.getDocument">
<button class="btn btn-success btn-block">Create Document</button>
</div>
In your store did u define the getter "getDocument", if so add a computed property in your component, it much cleaner and more reusable then referencing the store getters in the template directly:
computed : {
document: function() {
return this.$store.getters.getDocument;
}
}
in the template:
<div v-if="document.length">
<button class="btn btn-success btn-block">Create Document</button>
</div>

Modal window comment editing module (editable text)

I want to make, that during the ediditing comment action, I have modal window with comment text written inside textarea, and it is editable without deleting all text with clicking. I tried just to put value inside textarea or placing it in placeholder. But both options are wrong and doesnt work.
Can someone take a look on this code and give me an advice, how should I take for it.
editComment.html
<div class="modal-header">
<h3 class="modal-title" id="modal-title">Edytuj komentarz</h3>
</div>
<div class="modal-body" id="modal-body">
<div class="row">
<div class="col-sm-12">
<div class="row">
<div class="col-sm-12 form-group">
<label>Treść</label>
<textarea class="form-control input-sm"
name="description"
ng-maxlength="512"
ng-model="$ctrl.selected"
rows="6">{{comment.value()}}</textarea>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-raised btn-primary"
type="button"
ng-disabled="!$ctrl.selected"
ng-click="$ctrl.ok()">Zapisz
</button>
<button class="btn btn-raised btn-warning"
type="button"
ng-click="$ctrl.cancel()">Anuluj
</button>
</div>
editComment.js
(function() {
'use strict';
angular.module('settlerApplication').controller('EditCommentCtrl', function($uibModalInstance) {
var $ctrl = this;
$ctrl.ok = function() {
$uibModalInstance.close($ctrl.selected);
};
$ctrl.cancel = function() {
$uibModalInstance.dismiss('cancel');
};
});
})();
I'm not sure to understand what you are trying to achieve. But anyway : if you want to init your textarea's ng-model with $ctrl.foo (comment.value() in your case, from what I understood), you should either :
In the controller, init your $ctrl.selected variable with this value :
$ctrl.selected = $ctrl.foo;
Or, in your template, use ng-init :
<textarea class="form-control input-sm"
ng-init="$ctrl.selected = $ctrl.foo"
name="description"
ng-maxlength="512"
ng-model="$ctrl.selected"
rows="6"></textarea>
Ok, so I am going to explain that a little.
I have modal window like that:
I want to edit existing comments in this window. And so I want my comment appears instead of text: "Komentarz" (under: "Treść" after clicking in there). And I want that comment text to be editable, so I dont have to write it down again (put the whole text to that area). Is it make it a little better explained about my goal?

Angular Two Apps on the same page

What I am trying to do is render two Calendars on one page, each with a different data set. Currently the first Calendar loads correctly but the second calendar will not load. It doesn't appear to even try to load.
I am quite new to Angular, so I am not sure if what I am doing is allowed in the concept of a one page application, or if I should be doing it another way.
Open to all suggestions!
Calendar App Using: https://github.com/mattlewis92/angular-bootstrap-calendar
Front end (Trimmed down)
<div class="col-lg-9 panel panel-default" id="Calandars">
<button class="btn dropdown" data-toggle="collapse" data-target="#userCal" data-parent="#Calandars"><i class="icon-chevron-right"></i> User Calandar </button>
<button class="btn dropdown" data-toggle="collapse" data-target="#GlobalCal" data-parent="#Calandars"><i class="icon-chevron-right"></i> Global Calandar</button>
<div class="accordion-group">
<div id="userCal" class="collapse indent">
<!---User Calendar Configuration - Working Calendar-->
<div ng-app="UserCal" class="textfix">
<div ng-controller="Cal as vm">
<h2 class="text-center">{{ vm.calendarTitle }}</h2>
<mwl-calendar events="vm.events"
view="vm.calendarView"
view-title="vm.calendarTitle"
view-date="vm.viewDate"
on-event-click="vm.eventClicked(calendarEvent)"
on-event-times-changed="vm.eventTimesChanged(calendarEvent); calendarEvent.startsAt = calendarNewEventStart; calendarEvent.endsAt = calendarNewEventEnd"
edit-event-html="'<i class=\'glyphicon glyphicon-pencil\'></i>'"
delete-event-html="'<i class=\'glyphicon glyphicon-remove\'></i>'"
on-edit-event-click="vm.eventEdited(calendarEvent)"
on-delete-event-click="vm.eventDeleted(calendarEvent)"
cell-is-open="vm.isCellOpen"
day-view-start="06:00"
day-view-end="22:00"
day-view-split="30"
cell-modifier="vm.modifyCell(calendarCell)">
</mwl-calendar>
</div>
</div>
</div>
<div id="GlobalCal" class="collapse indent">
<!---Global Calandar Configuration -- None Working Calendar-->
<div ng-app="UserCal" class="textfix">
<div ng-controller="GlobalCalCon as vm">
<h2 class="text-center">{{ vm.calendarTitle }}</h2>
<mwl-calendar events="vm.events"
view="vm.calendarView"
view-title="vm.calendarTitle"
view-date="vm.viewDate"
on-event-click="vm.eventClicked(calendarEvent)"
on-event-times-changed="vm.eventTimesChanged(calendarEvent); calendarEvent.startsAt = calendarNewEventStart; calendarEvent.endsAt = calendarNewEventEnd"
edit-event-html="'<i class=\'glyphicon glyphicon-pencil\'></i>'"
delete-event-html="'<i class=\'glyphicon glyphicon-remove\'></i>'"
on-edit-event-click="vm.eventEdited(calendarEvent)"
on-delete-event-click="vm.eventDeleted(calendarEvent)"
cell-is-open="vm.isCellOpen"
day-view-start="06:00"
day-view-end="22:00"
day-view-split="30"
cell-modifier="vm.modifyCell(calendarCell)">
</mwl-calendar>
</div>
</div>
</div>
Javascript Behind
angular.module('UserCal', ['mwl.calendar', 'ui.bootstrap', 'ngAnimate'])
.controller('Cal', populateCal)
.controller('GlobalCalCon', populateGlobalCal);
function populateCal($http) {
Do Stuff
angular.copy(MyData, vm.events)
};
function populateGlobalCal($http) {
Do Diffrent Stuff
angular.copy(MyData, vm.events)
};
Well, In here you're using same module UserCal two times. This is your main SPA module so it will be only one time.
Please put ng-app="UserCal" to html/body tag and remove <div ng-app="UserCal" class="textfix"> from HTML code.
Now both the calender will work :)
cheers!
Its because you are using ng-app twice, you have to declare it only once on top of the page or best thing is declare it in ur index.html on html tag
On index.html:
<html ng-app="UserCal">
Or
On current page:
<div ng-app="UserCal">
<div ng-controller="Ctrl1">
// stuff goes herr
</div>
<div ng-controller="Ctrl1">
// stuff goes herr
</div>
</div>

disable dynamic id buttons with jQuery

I'm using VB.Net, MVC 5, razor and jQuery. I have a razor view that creates buttons I'm trying to disable on the user click. I generally accomplish this task using jQuery:
$('#id').prop("disabled", true);
My task is new to me in that my buttons are generated like this:
#For i As Integer = 0 To Model.hrmnValues.Count - 1
#<div class="col-md-3">
<a class="btn btn-primary btn-md" href="#" id="#Model.inventoryCategoryAttIDs(i)"
onclick="acceptChange('#Model.hrmnValues(i)',
#Model.inventoryCategoryAttIDs(i), #Model.uniqueItemID)">Accept Change</a>
</div>
Next
My onClick function is similar to this:
function acceptChange(newValue, categoryAttID, itemID) {
$('#categoryAttID').prop("disabled", true);
}
This obviously does not work, as it is looking for an id with the name of categoryAttID. I have also tried putting the categoryAttID into it's own variable like this:
var idToDisable = "#" + categoryAttID;
and then putting idToDisable into the jQuery call to disable the button, this did not work.
Given this situation how can I disable the button that is clicked?
There will be multiple buttons on this page making use of the function, the function actually performs an ajax call. The idea is to limit the user to performing one ajax call per button.
The html is rendered like this:
<div class="row">
<div class="col-md-3">
<font>First Name</font>
</div>
<div class="col-md-3">
<font>John</font>
</div>
<div class="col-md-3">
<font>No Record Found</font>
</div>
<div class="col-md-3">
<a class="btn btn-primary btn-md" href="#" id="2"
onclick="acceptChange('CHRISTOPHER', 2, 0)">Accept Change</a>
</div>
</div>
<div class="row">
<div class="col-md-3">
<font>Last Name</font>
</div>
<div class="col-md-3">
<font>MURRAY</font>
</div>
<div class="col-md-3">
<font>No Record Found</font>
</div>
<div class="col-md-3">
<a class="btn btn-primary btn-md" href="#" id="3"
onclick="acceptChange('MURRAY', 3, 0)">Accept Change</a>
</div>
You're already passing the button's id to your function as the second argument -
acceptChange('#Model.hrmnValues(i)',#Model.inventoryCategoryAttIDs(i), #Model.uniqueItemID)
So you can change your function to -
function acceptChange(newValue, categoryAttID, itemID) {
$('#' + categoryAttID).prop("disabled", true);
}
Also, there isn't a disabled property available for links (see - Mozilla Developer Network) if you want to disable your elements on click try using a button instead.
Since you appear to be using bootstrap after changing your links to buttons you might want to change your function to -
function acceptChange(newValue, categoryAttID, itemID) {
$('#' + categoryAttID).prop("disabled", true);
$('#' + categoryAttID).addClass("disabled");
}

Reset data on click for a different controller

I have two divs - the first contains the second. The contained div has its own controller. When I click an icon button in the container, I change a variable which then affects the visibility of the contained div.
It looks like this:
<div ng-controller="BarController">
<div class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<div class="col-lg-2 page-title">My Page</div>
<div class="col-lg-10">
<span class="actions">
<i class="fa fa-lg fa-download fa-inverse" tooltip="Download"
ng-click="showSecondaryBar=!showSecondaryBar"></i>
</span>
</div>
</div>
</div>
<div class="download navbar download-in download-out"
ng-class="{'myhidden': !showSecondaryBar}"
ng-cloak>
<div class="col-lg-offset-4 col-lg-4 form-inline form-group" ng-controller="TagsController">
<div class="download-label col-lg-6">
<label>Download by tags:</label>
</div>
<div class="download-tags col-lg-6">
<tags-input class="bootstrap" spellcheck="false" min-length="1" ng-model="tags" add-from-autocomplete-only="true">
<auto-complete source="loadTags($query)" min-length="1" load-on-down-arrow="true"
load-on-focus="true" max-results-to-show="5"
highlight-matched-text="false"></auto-complete>
</tags-input>
</div>
</div>
</div>
</div>
The <tags-input> is taken from ng-tags-input and I would like to reset the tags that were already typed to it whenever the icon button is clicked (which changes the visilibyt of the div that contains the ng-tags-input).
Problem is, because I have the TagsController which contains the data (tags) and this data is not visible in the BarController, I'm not sure how I can reset the tags array to become empty.
I thought of using a service but it fills like too much of a coupling. I would prefer to have a function in TagsController which is called upon click. But I can't figure out how to do it from another controller
You are right you have to use a service.
Why don't you use a broadcast as your TagsController is included in BarController?
You can include a scope.broadcast("Event") in BarController
Then a "on" listener on TagsController who will reset the tags array when "Event" Occur.
I would personnaly to this.
https://docs.angularjs.org/api/ng/type/$rootScope.Scope
You can use $broadcast on $rootScope to send an event to TagsController. So TagsController can receive this event by registering an event listener for it. See following example.
Refer to $rootScope API docs
angular.module('app',[])
.controller('ParentController', function($rootScope) {
var parentCtrl = this;
parentCtrl.someFlag = true;
parentCtrl.changeFlag = function() {
parentCtrl.someFlag = !parentCtrl.somFlag;
$rootScope.$broadcast('resettags', {'defaultTags': 'whatever_tag'});
}
})
.controller('ChildController', function($rootScope){
var childCtrl = this;
childCtrl.tags = "Some tags entered by user";
$rootScope.$on('resettags', function(event, args) {
childCtrl.tags = args.defaultTags;
});
});
.myHidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div id="main" ng-controller="ParentController as parentCtrl">
<button type="button" ng-click="parentCtrl.changeFlag()">Toggle</button>
<div ng-class="{'myHidden' : !parentCtrl.someFlag}">
<div ng-controller="ChildController as childCtrl">
<h1>{{childCtrl.tags}}</h1>
</div>
</div>
</div>
</div>

Categories

Resources